home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Blue / MoreAEM.cp < prev    next >
Encoding:
Text File  |  1996-02-19  |  95.9 KB  |  2,770 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        MoreAEM.c
  3.  
  4.     Contains:    C++ wrappers for the AppleEvent Manager
  5.  
  6.     Written by:    Greg Anderson
  7.  
  8.     Copyright:    © 1992-1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.         <31>     2/15/95    ga        
  11.  
  12. */
  13.  
  14. #ifdef MWTRACEBACKTABLES
  15. #pragma traceback on
  16. #endif
  17.  
  18. #include "MoreAEM.h"
  19.  
  20. #include <AppleEvents.h>
  21. #include <AERegistry.h>
  22. #include <Errors.h>
  23.  
  24. #include <AEPackObject.h>
  25. #include <AEObjects.h>
  26. #include <ASRegistry.h>
  27.  
  28. // #include "FinderRegistry.h"
  29.  
  30. #include "Exceptions.h"
  31. #include "Debug.h"
  32.  
  33.  
  34.  
  35. #pragma segment AEMStuff
  36.  
  37.  
  38. MakeTokenDescriptorProcPtr gNullContainerCreationProc = nil;
  39. ProcessDescriptorProcPtr gPreResolveProc = nil;
  40. MergeTokensProcPtr gMergeTokensProc = nil;
  41.  
  42. SInt16 TDescriptor::fCallbackFlags = kAEIDoMinimum;
  43.  
  44. #define kDayLengthInSecs    (24*60*60)
  45.  
  46.  
  47. //================================================================================
  48. // Class TStringCompareBehavior
  49. //================================================================================
  50.  
  51. class TStringCompareBehavior : public TAbstractCompareBehavior
  52. {
  53.     virtual CompareEnumeration CompareDynamicBehavior(const TAbstractDataReference& object1, const TAbstractDataReference& object2) const;
  54.     virtual Boolean ContainsDynamicBehavior(const TAbstractDataReference& object1, const TAbstractDataReference& object2) const;
  55.  
  56.     static Boolean IsTextType(DescType theType);
  57. };
  58.  
  59. //----------------------------------------------------------------------------------------
  60. // TStringCompareBehavior::IsTextType
  61. //----------------------------------------------------------------------------------------
  62. Boolean TStringCompareBehavior::IsTextType(DescType theType)
  63.     {
  64.     return (theType == typeAEText) || (theType == typeIntlText) || (theType == typeStyledText) || (theType == typeChar);
  65.     }
  66.  
  67. //----------------------------------------------------------------------------------------
  68. // TStringCompareBehavior::CompareDynamicBehavior
  69. //----------------------------------------------------------------------------------------
  70. CompareEnumeration TStringCompareBehavior::CompareDynamicBehavior(const TAbstractDataReference& object1, const TAbstractDataReference& object2) const
  71.     {
  72.     CompareEnumeration compareResult = kObjectKeysEqual;
  73.     
  74.     //
  75.     // We can compare any sort of textual objects; anything that isn't
  76.     // text will have to be handled by some other comparitor.
  77.     //
  78.     if(IsTextType(object1.DataType()) && IsTextType(object2.DataType()))
  79.         {
  80.         TConstDataReference object1Data(object1);
  81.         TConstDataReference object2Data(object2);
  82.         TDescriptor tempObject1Desc;
  83.         TDescriptor tempObject2Desc;
  84.         
  85.         //
  86.         // First, coerce the data to be a simple typeChar
  87.         // (International note:  we loose information such
  88.         // as the script code when we do this.  This routine
  89.         // is NOT a good example of how to compare text).
  90.         //
  91.         if(object1.DataType() != typeChar)
  92.             {
  93.             FailErr(AECoercePtr(object1.DataType(), object1.Data(), object1.DataLength(), typeChar, tempObject1Desc));
  94.             tempObject1Desc.Lock();
  95.             object1Data = TConstDataReference(tempObject1Desc);
  96.             }
  97.         if(object2.DataType() != typeChar)
  98.             {
  99.             FailErr(AECoercePtr(object2.DataType(), object2.Data(), object2.DataLength(), typeChar, tempObject2Desc));
  100.             tempObject2Desc.Lock();
  101.             object2Data = TConstDataReference(tempObject2Desc);
  102.             }
  103.         
  104.         //
  105.         // Now that we have two strings of typeChar, compare them
  106.         //
  107.         SInt32 compareLength = object1Data.DataLength() < object2Data.DataLength() ? object1Data.DataLength() :  object2Data.DataLength();
  108.         const char* data = object1Data.Data();
  109.         const char* compareWith = object2Data.Data();
  110.         
  111.         for(SInt32 i=0; i < compareLength; ++i)
  112.             {
  113.             unsigned char compareWithChar = *((unsigned char*)compareWith);
  114.             unsigned char dataChar = *((unsigned char*)data);
  115.             
  116.             if((compareWithChar >= 'a') && (compareWithChar <= 'z'))
  117.                 compareWithChar = compareWithChar - 'a' + 'A';
  118.             if((dataChar >= 'a') && (dataChar <= 'z'))
  119.                 dataChar = dataChar - 'a' + 'A';
  120.                 
  121.             if(compareWithChar > dataChar)
  122.                 {
  123.                 compareResult = kSecondObjectComesAfter;
  124.                 break;
  125.                 }
  126.             else if(compareWithChar < dataChar)
  127.                 {
  128.                 compareResult = kSecondObjectComesBefore;
  129.                 break;
  130.                 }
  131.             ++compareWith;
  132.             ++data;
  133.             }
  134.         
  135.         //
  136.         // If the first 'compareLength' bytes of the data stream are equal, then
  137.         // equality is based on the lengths of the strings
  138.         //
  139.         if(compareResult == kObjectKeysEqual)
  140.             {
  141.             if(object2Data.DataLength() > object1Data.DataLength())
  142.                 compareResult = kSecondObjectComesAfter;
  143.             if(object2Data.DataLength() < object1Data.DataLength())
  144.                 compareResult = kSecondObjectComesBefore;
  145.             }
  146.             
  147.         //
  148.         // Delete our temporary data, if we allocated it.
  149.         //
  150.         tempObject1Desc.Dispose();
  151.         tempObject2Desc.Dispose();
  152.         }
  153.     else
  154.         {
  155.         compareResult = TAbstractCompareBehavior::CompareDynamicBehavior(object1, object2);
  156.         }
  157.     
  158.     return compareResult;
  159.     }
  160.  
  161. //----------------------------------------------------------------------------------------
  162. // TStringCompareBehavior::ContainsDynamicBehavior
  163. //----------------------------------------------------------------------------------------
  164. Boolean TStringCompareBehavior::ContainsDynamicBehavior(const TAbstractDataReference& object1, const TAbstractDataReference& object2) const
  165.     {
  166.     Boolean containsResult = false;
  167.     
  168.     //
  169.     // We can compare any sort of textual objects; anything that isn't
  170.     // text will have to be handled by some other comparitor.
  171.     //
  172.     if(IsTextType(object1.DataType()) && IsTextType(object2.DataType()))
  173.         {
  174.         TConstDataReference object1Data(object1);
  175.         TConstDataReference object2Data(object2);
  176.         TDescriptor tempObject1Desc;
  177.         TDescriptor tempObject2Desc;
  178.         
  179.         //
  180.         // ◊Move these compare routines to MoreStrings, and make them use the cooler string-compare functions.
  181.         //
  182.         // First, coerce the data to be a simple typeChar
  183.         // (International note:  we loose information such
  184.         // as the script code when we do this.  This routine
  185.         // is NOT a good example of how to compare text).
  186.         //
  187.         if(object1.DataType() != typeChar)
  188.             {
  189.             FailErr(AECoercePtr(object1.DataType(), object1.Data(), object1.DataLength(), typeChar, tempObject1Desc));
  190.             object1Data = TConstDataReference(tempObject1Desc);
  191.             }
  192.         if(object2.DataType() != typeChar)
  193.             {
  194.             FailErr(AECoercePtr(object2.DataType(), object2.Data(), object2.DataLength(), typeChar, tempObject2Desc));
  195.             object2Data = TConstDataReference(tempObject1Desc);
  196.             }
  197.         
  198.         //
  199.         // Look for object2 inside of object1
  200.         //
  201.         SInt32 lengthDifference = object1.DataLength() - object2.DataLength();
  202.         const char* data = object1.Data();
  203.         
  204.         while(lengthDifference >= 0)
  205.             {
  206.             TConstDataReference partialString(object1.DataType(), data, object2.DataLength());
  207.             
  208.             if(partialString.Compare(object2) == kObjectKeysEqual)
  209.                 {
  210.                 containsResult = true;
  211.                 break;
  212.                 }
  213.             
  214.             --lengthDifference;
  215.             ++data;
  216.             }
  217.                     
  218.         //
  219.         // Delete our temporary data, if we allocated it.
  220.         //
  221.         tempObject1Desc.Dispose();
  222.         tempObject2Desc.Dispose();
  223.         }
  224.     else
  225.         {
  226.         containsResult = TAbstractCompareBehavior::ContainsDynamicBehavior(object1, object2);
  227.         }
  228.     
  229.     return containsResult;
  230.     }
  231.     
  232. //----------------------------------------------------------------------------------------
  233. // InstallStringCompareBehavior
  234. //
  235. // Add our cheezy roman-only string compare behavior
  236. //----------------------------------------------------------------------------------------
  237. void InstallStringCompareBehavior()
  238.     {
  239.     TStringCompareBehavior* compareBehavior = new TStringCompareBehavior;
  240.     
  241.     TAbstractDataReference::AddCompareBehavoir(compareBehavior);
  242.     }
  243.  
  244. //----------------------------------------------------------------------------------------
  245. // InstallNullContainerCreationProc: 
  246. //
  247. // The null container creation proc is used by TDescriptor::Resolve whenever it receives
  248. // a null descriptor to resolve.  This function is used to create a token for the null
  249. // container.
  250. //----------------------------------------------------------------------------------------
  251. void InstallNullContainerCreationProc(MakeTokenDescriptorProcPtr creationProc)
  252.     {
  253.     gNullContainerCreationProc = creationProc;
  254.     } // InstallNullContainerCreationProc 
  255.  
  256. //----------------------------------------------------------------------------------------
  257. // InstallPreResolveProc: 
  258. //
  259. // The PreResolveProc is called by TDescriptor::Resolve before it actually calls
  260. // AEResolve.  This allows special procs to handle things not understood by AEResolve
  261. // (alias records, for example).
  262. //----------------------------------------------------------------------------------------
  263. void InstallPreResolveProc(ProcessDescriptorProcPtr preResolveProc)
  264.     {
  265.     gPreResolveProc = preResolveProc;
  266.     } // InstallPreResolveProc 
  267.  
  268. //----------------------------------------------------------------------------------------
  269. // InstallMergeTokensProc: 
  270. //
  271. // The MergeTokensProc is called by TTokenDescriptor::AdoptToken whenever it needs to add
  272. // a token object to any token descriptor that already contains a token.  The merge token
  273. // proc is provided with two TAbstractScriptableObject*'s; it must return a
  274. // TAbstractScriptableObject* that has adopted the two tokens passed to it.
  275. //----------------------------------------------------------------------------------------
  276. void InstallMergeTokensProc(MergeTokensProcPtr mergeTokensProc)
  277.     {
  278.     gMergeTokensProc = mergeTokensProc;
  279.     } // InstallMergeTokensProc 
  280.  
  281. //----------------------------------------------------------------------------------------
  282. // CreateNullContainerToken: 
  283. //----------------------------------------------------------------------------------------
  284. TTokenDescriptor CreateNullContainerToken()
  285.     {
  286.     TTokenDescriptor nullContainer;
  287.     
  288.     if(gNullContainerCreationProc != nil)
  289.         nullContainer = (*gNullContainerCreationProc)();
  290.     
  291.     return nullContainer;
  292.     } // CreateNullContainerToken 
  293.  
  294. //========================================================================================
  295. // CLASS TDescriptor
  296. //
  297. // Class TDescriptor is a wrapper class for AEDesc objects.
  298. //========================================================================================
  299.  
  300.  
  301. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  302. //::  Descriptor memory management:
  303. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  304.  
  305.  
  306. //----------------------------------------------------------------------------------------
  307. // TDescriptor::Dispose:
  308. //
  309. // Disposed of the descriptor and the data stored inside it.  TDescriptors must be
  310. // disposed explicitly:  they are NOT disposed in their destructor.
  311. //----------------------------------------------------------------------------------------
  312. void TDescriptor::Dispose()
  313.     {
  314.     FailErr(AEDisposeDesc(*this));
  315.     } // TDescriptor::Dispose 
  316.     
  317. //----------------------------------------------------------------------------------------
  318. // TDescriptor::Clone:
  319. //
  320. // Return an exact copy of this descriptor
  321. //----------------------------------------------------------------------------------------
  322. TDescriptor TDescriptor::Clone() const
  323.     {
  324.     TDescriptor clonedDescriptor;
  325.     
  326.     clonedDescriptor.SetDescriptorData(*this);
  327.     
  328.     return clonedDescriptor;
  329.     } // TDescriptor::Clone 
  330.  
  331. //----------------------------------------------------------------------------------------
  332. // TDescriptor::AdoptDescriptor: 
  333. //----------------------------------------------------------------------------------------
  334. void TDescriptor::AdoptDescriptor(TDescriptor& desc)
  335.     {
  336.     fAEDesc = desc;
  337.     desc.ClearDescriptor();
  338.     } // TDescriptor::AdoptDescriptor 
  339.  
  340. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  341. //::  Comparison methods
  342. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  343.  
  344. //----------------------------------------------------------------------------------------
  345. // TDescriptor::Compare: 
  346. //
  347. // Compare two descriptors.  ComparisonOperator should be one of the following:
  348. //
  349. // kAEEquals, kASNotEqual, kAEGreaterThan, kAEGreaterThanEquals, kAELessThan,
  350. // kASLessThanOrEqual, kAEBeginsWith, kAEEndsWith, or kAEContains
  351. //----------------------------------------------------------------------------------------
  352. Boolean TDescriptor::Compare(DescType comparisonOperator, const TDescriptor& compareWith) const
  353.     {
  354.     Boolean compareResult = false;
  355.     
  356.     //
  357.     // It might be nice to try to do a type coercion here, but for now
  358.     // we only compare descriptors of the same type
  359.     //
  360.     if(this->DescriptorType() != compareWith.DescriptorType())
  361.         FailErr(errAEEventNotHandled);
  362.  
  363.     return CompareTypedData(comparisonOperator, *this, compareWith);
  364.     } // TDescriptor::Compare
  365.  
  366.  
  367. //----------------------------------------------------------------------------------------
  368. // ReverseComparisonOperator: 
  369. //
  370. // Sometimes it cannot be avoided:  we must convert from "a compareisonOp b" to
  371. // "b reverseComparisonOp a".  This routine determines what the reverse operation
  372. // should be.
  373. //----------------------------------------------------------------------------------------
  374. DescType ReverseComparisonOperator(DescType comparisonOperator)
  375.     {
  376.     DescType result = comparisonOperator;
  377.     
  378.     switch(comparisonOperator)
  379.         {
  380.         case kAEEquals:
  381.         case kASNotEqual:
  382.             {
  383.             result = comparisonOperator;
  384.             }
  385.             break;
  386.             
  387.         case kAEGreaterThan:
  388.             {
  389.             result = kAELessThan;
  390.             }
  391.             break;
  392.         
  393.         case kAEGreaterThanEquals:
  394.             {
  395.             result = kAELessThanEquals;
  396.             }
  397.             break;
  398.         
  399.         case kAELessThan:
  400.             {
  401.             result = kAEGreaterThan;
  402.             }
  403.             break;
  404.         
  405.         case kAELessThanEquals:
  406.             {
  407.             result = kAEGreaterThanEquals;
  408.             }
  409.             break;
  410.  
  411.         case kAEBeginsWith:
  412.             {
  413.             result = kAEAtTheBeginningOf;
  414.             }
  415.             break;
  416.             
  417.         case kAEEndsWith:
  418.             {
  419.             result = kAEAtTheEndOf;
  420.             }
  421.             break;
  422.             
  423.         case kAEContains:
  424.             {
  425.             result = kAEIsContainedIn;
  426.             }
  427.             break;
  428.  
  429.         case kAEAtTheBeginningOf:
  430.             {
  431.             result = kAEBeginsWith;
  432.             }
  433.             break;
  434.             
  435.         case kAEAtTheEndOf:
  436.             {
  437.             result = kAEEndsWith;
  438.             }
  439.             break;
  440.             
  441.         case kAEIsContainedIn:
  442.             {
  443.             result = kAEContains;
  444.             }
  445.             break;
  446.         
  447.         //
  448.         // ◊Script:  We should fail if we don't recognize the comparison operator
  449.         //
  450.         default:
  451.             {
  452.             result = 0;
  453.             }
  454.         }
  455.     
  456.     return result;
  457.     }
  458.     
  459. //----------------------------------------------------------------------------------------
  460. // InterpretCompareResult:
  461. //
  462. // Given two keys and a comparison opperator, this function determines if
  463. // the comparison between key2 and key1 is true or false.  key1 and key2 should
  464. // be either two long integers representing the various values of the two descriptors
  465. // being compared, or key1 may be set to 0 and key2 set to -1 (key2 < key1), 0
  466. // (key1 == key2) or 1 (key2 > key1).
  467. //
  468. // This function is used by GeneralCompare, which is used by TDescriptor::Compare
  469. //----------------------------------------------------------------------------------------
  470. Boolean InterpretCompareResult(DescType comparisonOperator, SInt32 key1, SInt32 key2 )
  471.     {
  472.     switch(comparisonOperator)
  473.         {
  474.         case kAEEquals:
  475.             {
  476.             return key1 == key2;
  477.             }
  478.         
  479.         case kASNotEqual:
  480.             {
  481.             return key1 != key2;
  482.             }
  483.         
  484.         case kAEGreaterThan:
  485.             {
  486.             return key1 > key2;
  487.             }
  488.         
  489.         case kAEGreaterThanEquals:
  490.             {
  491.             return key1 >= key2;
  492.             }
  493.         
  494.         case kAELessThan:
  495.             {
  496.             return key1 < key2;
  497.             }
  498.         
  499.         case kAELessThanEquals:
  500.             {
  501.             return key1 <= key2;
  502.             }
  503.         
  504.         //
  505.         // ••• Perhaps we should fail if we don't recognize the comparisonOperator
  506.         //
  507.         default:
  508.             {
  509.             return false;
  510.             }
  511.         }
  512.     } // InterpretCompareResult 
  513.  
  514. //----------------------------------------------------------------------------------------
  515. // CompareTypedData
  516. //----------------------------------------------------------------------------------------
  517. Boolean CompareTypedData(DescType comparisonOperator, const TAbstractDataReference& compareThisRef, const TAbstractDataReference& compareWithRef)
  518.     {
  519.     Boolean compareResult = false;
  520.     
  521.     switch(comparisonOperator)
  522.         {
  523.         case kAEEquals:        
  524.         case kASNotEqual:
  525.         case kAEGreaterThan:
  526.         case kAEGreaterThanEquals:
  527.         case kAELessThan:
  528.         case kASLessThanOrEqual:
  529.             {
  530.             compareResult = InterpretCompareResult(comparisonOperator, compareThisRef.Compare(compareWithRef), 0 );
  531.             break;
  532.             }
  533.         
  534.         //
  535.         // Question:  is this begins-with clipping bogus?
  536.         //        
  537.         case kAEBeginsWith:
  538.             {
  539.             if(compareWithRef.DataLength() > compareThisRef.DataLength())
  540.                 compareResult = false;
  541.             else
  542.                 {
  543.                 TConstDataReference beginningOfThis(compareThisRef.DataType(), compareThisRef.Data(), compareWithRef.DataLength());
  544.                 compareResult = InterpretCompareResult(kAEEquals, beginningOfThis.Compare(compareWithRef), 0 );
  545.                 }
  546.             break;
  547.             }
  548.             
  549.         //
  550.         // Question:  is this ends-with clipping bogus?
  551.         //        
  552.         case kAEEndsWith:
  553.             {
  554.             SInt32 sizeDifference = compareThisRef.DataLength() - compareWithRef.DataLength();
  555.             if(sizeDifference < 0)
  556.                 compareResult = false;
  557.             else
  558.                 {
  559.                 TConstDataReference endOfThis(compareThisRef.DataType(), compareThisRef.Data() + sizeDifference, compareWithRef.DataLength());
  560.                 compareResult = InterpretCompareResult(kAEEquals, endOfThis.Compare(compareWithRef), 0 );
  561.                 }
  562.             break;
  563.             }
  564.  
  565.         case kAEContains:
  566.             {
  567.             compareResult = compareThisRef.Contains(compareWithRef);
  568.             break;
  569.             }
  570.  
  571.         case kAEAtTheBeginningOf:
  572.             {
  573.             compareResult = CompareTypedData(kAEBeginsWith, compareWithRef, compareThisRef);
  574.             break;
  575.             }
  576.             
  577.         case kAEAtTheEndOf:
  578.             {
  579.             compareResult = CompareTypedData(kAEEndsWith, compareWithRef, compareThisRef);
  580.             break;
  581.             }
  582.  
  583.         case kAEIsContainedIn:
  584.             {
  585.             compareResult = compareWithRef.Contains(compareThisRef);
  586.             break;
  587.             }
  588.         
  589.         default:
  590.             {
  591.             FailErr(errAEEventNotHandled);
  592.             break;
  593.             }
  594.         }
  595.     
  596.     return compareResult;
  597.     } // CompareTypedData
  598.  
  599. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  600. //::  Canonical get and set data accessors
  601. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  602.  
  603. //----------------------------------------------------------------------------------------
  604. // TDescriptor::GetDescriptorData
  605. //----------------------------------------------------------------------------------------
  606. void TDescriptor::GetDescriptorData(TUpdataDataReference& buffer, DescType typeToCoerceTo /*= typeWildCard*/) const
  607.     {
  608.     if(this->DataHandle())
  609.         {
  610.         if((typeToCoerceTo == typeWildCard) || (this->DescriptorType() == typeToCoerceTo))
  611.             {
  612.             //
  613.             // Don't be tempted to use our operator TDescriptorDataReference to do
  614.             // a simple buffer.CopyFrom(*this), because when buffer.CopyFrom invokes
  615.             // TDescriptorDataReference::CopyTo, CopyTo will call this routine and
  616.             // you'll never get out of the loop.
  617.             //
  618.             TConstDataReference inlineDataReference(this->DescriptorType(), *this->DataHandle(), this->DataSize());
  619.             buffer.CopyFrom(inlineDataReference, true);
  620.             }
  621.         else
  622.             {
  623.             TDescriptor coercedData = Coerce(typeToCoerceTo);
  624.             coercedData.GetDescriptorData(buffer);
  625.             coercedData.Dispose();
  626.             }
  627.         }
  628.     } // TDescriptor::GetDescriptorData
  629.  
  630. //----------------------------------------------------------------------------------------
  631. // TDescriptor::SetDescriptorData: 
  632. //----------------------------------------------------------------------------------------
  633. void TDescriptor::SetDescriptorData(const TAbstractDataReference& data, DescType typeToCoerceTo /*= typeWildCard*/)
  634.     {
  635.     if((typeToCoerceTo == typeWildCard) || (data.DataType() == typeToCoerceTo))
  636.         FailErr(AECreateDesc(data.DataType(), (const Ptr)data.Data(), data.DataLength(), *this));
  637.     else
  638.         FailErr(AECoercePtr(data.DataType(), (const Ptr)data.Data(), data.DataLength(), typeToCoerceTo, *this));
  639.     } // TDescriptor::SetDescriptorData 
  640.  
  641. //----------------------------------------------------------------------------------------
  642. // TDescriptor::SetDescriptorData: 
  643. //----------------------------------------------------------------------------------------
  644. void TDescriptor::SetDescriptorData(const TDescriptor& desc)
  645.     {
  646.     FailErr(AEDuplicateDesc(desc, *this));
  647.     } // TDescriptor::SetDescriptorData 
  648.  
  649. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  650. //::  Data coercion
  651. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  652.  
  653. //----------------------------------------------------------------------------------------
  654. // TDescriptor::AttemptToCoerce:
  655. //----------------------------------------------------------------------------------------
  656. TDescriptor TDescriptor::AttemptToCoerce(DescType typeToCoerceTo, OSErr& err) const
  657.     {
  658.     TDescriptor coercedDescriptor;
  659.     
  660.     err = AECoerceDesc(*this,typeToCoerceTo,coercedDescriptor);
  661.     
  662.     return coercedDescriptor;
  663.     } // TDescriptor::AttemptToCoerce 
  664.  
  665. //----------------------------------------------------------------------------------------
  666. // TDescriptor::Coerce:
  667. //
  668. // Require that this object be coerced to the specified data type.  This method will
  669. // fail if the coercion does not work.
  670. //----------------------------------------------------------------------------------------
  671. TDescriptor TDescriptor::Coerce(DescType typeToCoerceTo) const
  672.     {
  673.     TDescriptor coercedDescriptor;
  674.     
  675.     FailErr(AECoerceDesc(*this,typeToCoerceTo,coercedDescriptor));
  676.     
  677.     return coercedDescriptor;
  678.     } // TDescriptor::Coerce 
  679.  
  680. //----------------------------------------------------------------------------------------
  681. // TDescriptor::AttemptCoerceInPlace:
  682. //
  683. // Try to coerce the type of the descriptor to something else.  This method will
  684. // NOT fail if the coercion could not be done.
  685. //----------------------------------------------------------------------------------------
  686. OSErr TDescriptor::AttemptCoerceInPlace(DescType typeToCoerceTo)
  687.     {
  688.     OSErr err = noErr;
  689.     
  690.     if(this->DescriptorType() != typeToCoerceTo)
  691.         {
  692. #if 1
  693.         err = AECoerceDesc(*this,typeToCoerceTo, *this);
  694. #else //◊
  695.         //
  696.         // This way works, but the data handle of this descriptor
  697.         // is disposed an replaced with a new copy.  This isn't
  698.         // so hot if you have a copy of an AEDesc that you'd like
  699.         // to coerce that someone else is going to dispose later.
  700.         //
  701.         // In short, preserveHandle == kAllowHandleReallocation is
  702.         // faster, but more dangerous.
  703.         //
  704.         if(preserveHandle == kAllowHandleReallocation)
  705.             err = AECoerceDesc(*this,typeToCoerceTo, *this);
  706.         else
  707.             {
  708.             TDescriptor tempDescriptor;
  709.             
  710.             // If AECoerceDesc returns a non-zero result code, then
  711.             // tempDescriptor will be typeNull, and we don't need to
  712.             // worry about disposing of it.
  713.             err = AECoerceDesc(*this,typeToCoerceTo, tempDescriptor);
  714.     
  715.             if(err == noErr)
  716.                 {            
  717.                 Try
  718.                     {
  719.                     Handle initialHandle = this->DataHandle();
  720.                     Handle coercedHandle = tempDescriptor.DataHandle();
  721.                     
  722.                     //
  723.                     // If doing a coerce-in-place, try to do a SetHandleSize
  724.                     // and then a BlockMove so that we end up using the same
  725.                     // handle when we exit as we had when we entered.  To do
  726.                     // otherwise is to invite double-dispose/memory leak problems
  727.                     // if some other peice of code still has a reference to
  728.                     // the descriptor before it was coerced
  729.                     //
  730.                     if((initialHandle != nil) && (coercedHandle != nil))
  731.                         {
  732.                         Size coercedSize = GetHandleSize(coercedHandle);
  733.                         SetHandleSize(initialHandle, coercedSize);
  734.                         FailErr(MemError());
  735.                         BlockMoveData(*coercedHandle, *initialHandle, coercedSize);
  736.                         this->fDescriptorType = tempDescriptor.DescriptorType();
  737.                         tempDescriptor.Dispose();
  738.                         }
  739.                     //
  740.                     // There are a couple of rare cases (typeTrue and typeFalse)
  741.                     // where the data handle is nil
  742.                     //
  743.                     else
  744.                         {
  745.                         //
  746.                         // It's undesirable to go from a nil-handle to a non-nil
  747.                         // handle, or visa-versa.  Don't do it.  Use 'Coerce'
  748.                         // rather than 'CoerceInPlace' if this is necessary.
  749.                         //
  750.                         if((initialHandle != nil) || (coercedHandle != nil))
  751.                             ASSERTPRINT(false, ("Potentially undesirable coerce-in-place"));
  752.                         //
  753.                         // Try to dispose of the old descriptor (ignoring errors)
  754.                         // and then plug in the values from the coerced descriptor
  755.                         //
  756.                         AEDisposeDesc(*this);
  757.                         this->AdoptDescriptor(tempDescriptor);
  758.                         }
  759.                     }
  760.                 Catch(err)
  761.                     {
  762.                     tempDescriptor.Dispose();
  763.                     }
  764.                 }
  765.             }
  766. #endif
  767.         }
  768.     
  769.     return err;
  770.     } // TDescriptor::AttemptCoerceInPlace 
  771.  
  772. //----------------------------------------------------------------------------------------
  773. // TDescriptor::CoerceInPlace:
  774. //
  775. // Require that this object be coerced to the specified data type.  This method will
  776. // fail if the coercion does not work.
  777. //----------------------------------------------------------------------------------------
  778. void TDescriptor::CoerceInPlace(DescType typeToCoerceTo)
  779.     {
  780.     FailErr(this->AttemptCoerceInPlace(typeToCoerceTo));
  781.     } // TDescriptor::CoerceInPlace 
  782.  
  783. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  784. //::  A multitude of ways to get descriptor data
  785. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  786.  
  787. //----------------------------------------------------------------------------------------
  788. // TDescriptor::GetBooleanData
  789. //----------------------------------------------------------------------------------------
  790. Boolean TDescriptor::GetBooleanData() const
  791.     {
  792.     Boolean result = 0;
  793.     
  794.     this->GetDescriptorData(TUpdataDataReference(typeBoolean, (char*)&result, sizeof(Boolean), sizeof(Boolean)), typeBoolean);
  795.     
  796.     return result;
  797.     }
  798.  
  799. //----------------------------------------------------------------------------------------
  800. // TDescriptor::GetSInt32Data
  801. //----------------------------------------------------------------------------------------
  802. SInt32 TDescriptor::GetSInt32Data() const
  803.     {
  804.     SInt32 result = 0;
  805.     
  806.     this->GetDescriptorData(TUpdataDataReference(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32)), typeSInt32);
  807.     
  808.     return result;
  809.     }
  810.  
  811. //----------------------------------------------------------------------------------------
  812. // TDescriptor::GetUInt32Data
  813. //----------------------------------------------------------------------------------------
  814. UInt32 TDescriptor::GetUInt32Data() const
  815.     {
  816.     UInt32 result = 0;
  817.     
  818.     this->GetDescriptorData(TUpdataDataReference(typeUInt32, (char*)&result, sizeof(UInt32), sizeof(UInt32)), typeUInt32);
  819.     
  820.     return result;
  821.     }
  822.  
  823. //----------------------------------------------------------------------------------------
  824. // TDescriptor::GetSInt64Data
  825. //----------------------------------------------------------------------------------------
  826. SInt64 TDescriptor::GetSInt64Data() const
  827.     {
  828.     SInt64 result;
  829.     
  830.     this->GetDescriptorData(TUpdataDataReference(typeSInt64, (char*)&result, sizeof(SInt64), sizeof(SInt64)), typeSInt64);
  831.     
  832.     return result;
  833.     }
  834.  
  835. //----------------------------------------------------------------------------------------
  836. // TDescriptor::GetDescTypeData
  837. //----------------------------------------------------------------------------------------
  838. DescType TDescriptor::GetDescTypeData(DescType expectedType /*= typeType*/) const
  839.     {
  840.     DescType result = 0;
  841.     
  842.     this->GetDescriptorData(TUpdataDataReference(expectedType, (char*)&result, sizeof(DescType), sizeof(DescType)), expectedType);
  843.     
  844.     return result;
  845.     }
  846.  
  847. //----------------------------------------------------------------------------------------
  848. // TDescriptor::GetPSNData
  849. //----------------------------------------------------------------------------------------
  850. ProcessSerialNumber TDescriptor::GetPSNData() const
  851.     {
  852.     ProcessSerialNumber result;
  853.     
  854.     this->GetDescriptorData(TUpdataDataReference(typeProcessSerialNumber, (char*)&result, sizeof(ProcessSerialNumber), sizeof(ProcessSerialNumber)), typeProcessSerialNumber);
  855.     
  856.     return result;
  857.     }
  858.  
  859. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  860. //::  A multitude of ways to set descriptor data
  861. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  862.  
  863. //----------------------------------------------------------------------------------------
  864. // TDescriptor::SetBooleanData
  865. //----------------------------------------------------------------------------------------
  866. void TDescriptor::SetBooleanData(const Boolean& data)
  867.     {
  868.     this->SetDescriptorData(TConstDataReference(typeBoolean, (char*)&data, sizeof(Boolean)));
  869.     }
  870.  
  871. //----------------------------------------------------------------------------------------
  872. // TDescriptor::SetSInt32Data
  873. //----------------------------------------------------------------------------------------
  874. void TDescriptor::SetSInt32Data(const SInt32& data)
  875.     {
  876.     this->SetDescriptorData(TConstDataReference(typeSInt32, (char*)&data, sizeof(SInt32)));
  877.     }
  878.  
  879. //----------------------------------------------------------------------------------------
  880. // TDescriptor::SetUInt32Data
  881. //----------------------------------------------------------------------------------------
  882. void TDescriptor::SetUInt32Data(const UInt32& data)
  883.     {
  884.     this->SetDescriptorData(TConstDataReference(typeUInt32, (char*)&data, sizeof(UInt32)));
  885.     }
  886.  
  887. //----------------------------------------------------------------------------------------
  888. // TDescriptor::SetSInt64Data
  889. //----------------------------------------------------------------------------------------
  890. void TDescriptor::SetSInt64Data(const SInt64& data)
  891.     {
  892.     this->SetDescriptorData(TConstDataReference(typeSInt64, (char*)&data, sizeof(SInt64)));
  893.     }
  894.  
  895. //----------------------------------------------------------------------------------------
  896. // TDescriptor::SetDescTypeData
  897. //----------------------------------------------------------------------------------------
  898. void TDescriptor::SetDescTypeData(const SInt32& data, DescType dataType /*= typeType*/)
  899.     {
  900.     this->SetDescriptorData(TConstDataReference(dataType, (char*)&data, sizeof(DescType)));
  901.     }
  902.  
  903. //----------------------------------------------------------------------------------------
  904. // TDescriptor::SetPSNData
  905. //----------------------------------------------------------------------------------------
  906. void TDescriptor::SetPSNData(const ProcessSerialNumber& psn)
  907.     {
  908.     this->SetDescriptorData(TConstDataReference(typeProcessSerialNumber, (char*)&psn, sizeof(ProcessSerialNumber)));
  909.     }
  910.  
  911. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  912. //::  List methods
  913. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  914.  
  915. //----------------------------------------------------------------------------------------
  916. // TDescriptor::CreateList:
  917. //
  918. // Create an empty descriptor list or AERecord with factored data.  The default
  919. // parameters cause this routine to create an empty list with no factored data.
  920. //----------------------------------------------------------------------------------------
  921. void TDescriptor::CreateList(Boolean isRecord, Ptr factoringPtr, Size factoredSize)
  922.     {
  923.     FailErr(AECreateList(factoringPtr, factoredSize, isRecord, *this));
  924.     } // TDescriptor::CreateList 
  925.  
  926. //----------------------------------------------------------------------------------------
  927. // TDescriptor::CoerceToList: 
  928. //
  929. // If this descriptor is null, an empty list is created.  If this descriptor is not
  930. // empty, then a list is created and this descriptor is placed inside it.  If this
  931. // descriptor is already a list, then no action is taken.
  932. //----------------------------------------------------------------------------------------
  933. void TDescriptor::CoerceToList()
  934.     {
  935.     if(this->IsNullDescriptor())
  936.         {
  937.         this->CreateList();
  938.         }
  939.     else if(this->DescriptorType() != typeAEList)
  940.         {
  941.         this->CoerceInPlace(typeAEList);
  942.         }
  943.     } // TDescriptor::CoerceToList 
  944.     
  945. //----------------------------------------------------------------------------------------
  946. // TDescriptor::CountItems:
  947. //
  948. // Count the items in a descriptor list. If this descriptor is not of typeAEList, then it
  949. // only has one item, and if the descriptor is null, then it has no items.
  950. //----------------------------------------------------------------------------------------
  951. UInt32 TDescriptor::CountItems() const
  952.     {
  953.     UInt32 items = 1;
  954.     if(this->IsNullDescriptor())
  955.         items = 0;
  956.     else if((this->DescriptorType() == typeAEList) || (this->DescriptorType() == typeAERecord))
  957.         FailErr(AECountItems(*this, (SInt32*)&items));
  958.     return items;
  959.     } // TDescriptor::CountItems 
  960.  
  961. //----------------------------------------------------------------------------------------
  962. // TDescriptor::GetNthItem:
  963. //
  964. // Get the indexed descriptor from an event.  This method will fail if given an index
  965. // less than one or greater than the count returned by TDescriptor::CountItems.
  966. // The descriptor returned is _always_ a copy that must be disposed of with
  967. // TDescriptor::Dispose.
  968. //----------------------------------------------------------------------------------------
  969. TDescriptor TDescriptor::GetNthItem(SInt32 index, DescType desiredType, AEKeyword* key) const
  970.     {
  971.     TDescriptor descriptor;
  972.     AEKeyword ignoreKey;
  973.     
  974.     if(key == nil)
  975.         key = &ignoreKey;
  976.         
  977.     //
  978.     // We can "GetNthItem" on an item that is not of typeAEList
  979.     // if the index is one; we do this by cloning ourself
  980.     // (n.b. AERecords are also lists)
  981.     //
  982.     if((DescriptorType() != typeAEList) && (DescriptorType() != typeAERecord))
  983.         {
  984.         if(index != 1)
  985.             FailErr(errAEIllegalIndex);
  986.         
  987.         *key = typeWildCard; 
  988.         descriptor = this->Clone();
  989.         }
  990.     else
  991.         {
  992.         FailErr(AEGetNthDesc(*this, index, desiredType, key, descriptor));
  993.         }
  994.     
  995.     return descriptor;
  996.     } // TDescriptor::GetNthItem 
  997.  
  998. //----------------------------------------------------------------------------------------
  999. // TDescriptor::GetNthItemData
  1000. //----------------------------------------------------------------------------------------
  1001. void TDescriptor::GetNthItemData(SInt32 index, TUpdataDataReference& buffer, DescType desiredType, AEKeyword* key) const
  1002.     {
  1003.     AEKeyword ignoreKey;
  1004.     
  1005.     if(key == nil)
  1006.         key = &ignoreKey;
  1007.         
  1008.     //
  1009.     // We can "GetNthItem" on an item that is not of typeAEList
  1010.     // if the index is one; we do this by cloning ourself
  1011.     // (n.b. AERecords are also lists)
  1012.     //
  1013.     if((DescriptorType() != typeAEList) && (DescriptorType() != typeAERecord))
  1014.         {
  1015.         if(index != 1)
  1016.             FailErr(errAEIllegalIndex);
  1017.         
  1018.         *key = typeWildCard; 
  1019.         this->GetDescriptorData(buffer);
  1020.         }
  1021.     else
  1022.         {
  1023.         DescType actualType;
  1024.         SInt32 actualSize = 0;
  1025.         
  1026.         FailErr(AEGetNthPtr(*this, index, desiredType, key, &actualType, buffer.Data(), buffer.MaxLength(), &actualSize));
  1027.         buffer.SetDataLength(actualSize);
  1028.         buffer.SetDataType(actualType);
  1029.         }
  1030.     }
  1031.     
  1032. //----------------------------------------------------------------------------------------
  1033. // TDescriptor::AddItemToList:
  1034. //
  1035. // Add data to a descriptor list at a specified index, replacing any item already stored
  1036. // at that position.
  1037. //----------------------------------------------------------------------------------------
  1038. void TDescriptor::AddItemToList(SInt32 index, const TDescriptor& data)
  1039.     {
  1040.     //
  1041.     // If the list is completely empty, just put the data directly into
  1042.     // this descriptor (don't make a list)
  1043.     //
  1044.     if(this->IsNullDescriptor())
  1045.         {
  1046.         this->SetDescriptorData(data);
  1047.         }
  1048.     else
  1049.         {
  1050.         //
  1051.         // If we're not a list yet, we'd better make ourselves one now.
  1052.         //
  1053.         if(this->DescriptorType() != typeAEList)
  1054.             this->CoerceToList();
  1055.         FailErr(AEPutDesc(*this, index, data));
  1056.         }
  1057.     } // TDescriptor::AddItemToList 
  1058.  
  1059. //----------------------------------------------------------------------------------------
  1060. // TDescriptor::AddItemToList:
  1061. //
  1062. // Add data to a descriptor list at the end of the list
  1063. //----------------------------------------------------------------------------------------
  1064. void TDescriptor::AddItemToList(const TDescriptor& data)
  1065.     {
  1066.     this->AddItemToList(0,data);
  1067.     } // TDescriptor::AddItemToList 
  1068.  
  1069. //----------------------------------------------------------------------------------------
  1070. // TDescriptor::AddItemToList: 
  1071. //----------------------------------------------------------------------------------------
  1072. void TDescriptor::AddItemToList(SInt32 index, const TAbstractDataReference& data)
  1073.     {
  1074.     //
  1075.     // If the list is completely empty, we'd better make an empty list
  1076.     // (the type coercion from null to typeAEList probably works,
  1077.     // but I have not tested it yet; the following two lines may
  1078.     // be superfluous)
  1079.     //
  1080.     if(this->IsNullDescriptor())
  1081.         this->CreateList();
  1082.     
  1083.     //
  1084.     // If we're not a list yet, we'd better make ourselves one now.
  1085.     //
  1086.     if(this->DescriptorType() != typeAEList)
  1087.         this->CoerceInPlace(typeAEList);
  1088.     
  1089.     //
  1090.     // Put the data into the list
  1091.     //
  1092.     FailErr(AEPutPtr(*this,index,data.DataType(),data.Data(),data.DataLength()));
  1093.     } // TDescriptor::AddItemToList 
  1094.  
  1095. //----------------------------------------------------------------------------------------
  1096. // TDescriptor::AddItemToList: 
  1097. //----------------------------------------------------------------------------------------
  1098. void TDescriptor::AddItemToList(const TAbstractDataReference& data)
  1099.     {
  1100.     this->AddItemToList(0,data);
  1101.     } // TDescriptor::AddItemToList 
  1102.  
  1103. //----------------------------------------------------------------------------------------
  1104. // TDescriptor::AppendList:
  1105. //
  1106. // Append a list onto the end of this one.  The list passed in may be a null descriptor
  1107. // or a single item as well as a list.
  1108. //----------------------------------------------------------------------------------------
  1109. void TDescriptor::AppendList(const TDescriptor& list)
  1110.     {
  1111.     OSErr err = noErr;
  1112.     
  1113.     //
  1114.     // Take no action if our input is null
  1115.     //
  1116.     if(list.IsNullDescriptor() == false)
  1117.         {
  1118.         //
  1119.         // If this descriptor is a null descriptor, then we just want
  1120.         // to copy the incoming list.
  1121.         //
  1122.         // In the past we did not do this check, which resulted in
  1123.         // the unfortunate side effect of converting a single-item
  1124.         // list into a single (non-list) descriptor whenever said
  1125.         // list was 'AppendList'ed into an empty list.  While this
  1126.         // may be more efficient, it really hosed us over in the case
  1127.         // of GetData on the selection property, which is SUPPOSED
  1128.         // to return a single-item list (as opposed to a single
  1129.         // descriptor) if there is only one item in the list.  (This
  1130.         // is quite different from most other objects, which are
  1131.         // supposed to return single descriptors instead of single-
  1132.         // item lists whenever there is only one object in the result.)
  1133.         //
  1134.         if(this->IsNullDescriptor())
  1135.             {
  1136.             this->SetDescriptorData(list);
  1137.             }
  1138.         //
  1139.         // Script:  in the past we did not check to see
  1140.         // if the list was an AERecord; this was very
  1141.         // bad because appending mutliple records together
  1142.         // into a list didn't work correctly (we would
  1143.         // iterate over the record--which works--
  1144.         // and add the data without its key!).
  1145.         //
  1146.         // Actually, we'll be a bit more efficient and
  1147.         // test for non-lists instead
  1148.         //
  1149.         else if(list.DescriptorType() != typeAEList)
  1150.             this->AddItemToList(list);        
  1151.         else
  1152.             {
  1153.             Try
  1154.                 {
  1155.                 for(TDescriptorIterator iter(list); iter.More(); iter.Next())
  1156.                     {
  1157.                     this->AddItemToList(iter.Current());
  1158.                     }
  1159.                 }
  1160.             Catch(err)
  1161.                 {
  1162.                 Throw(err);
  1163.                 }
  1164.             }
  1165.         }
  1166.     } // TDescriptor::AppendList 
  1167.  
  1168. //----------------------------------------------------------------------------------------
  1169. // TDescriptor::AppendListAndDispose: 
  1170. //----------------------------------------------------------------------------------------
  1171. void TDescriptor::AppendListAndDispose(TDescriptor& list)
  1172.     {
  1173.     if(this->IsNullDescriptor())
  1174.         {
  1175.         this->AdoptDescriptor(list);
  1176.         }
  1177.     else
  1178.         {
  1179.         this->AppendList(list);
  1180.         list.Dispose();
  1181.         }
  1182.     } // TDescriptor::AppendListAndDispose 
  1183.  
  1184.  
  1185. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1186. //::  Record methods
  1187. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1188.  
  1189. //----------------------------------------------------------------------------------------
  1190. // TDescriptor::MakeAERecord
  1191. //----------------------------------------------------------------------------------------
  1192. void TDescriptor::MakeAERecord()
  1193.     {
  1194.     this->CreateList(kMakeAERecord);
  1195.     }
  1196.  
  1197. //----------------------------------------------------------------------------------------
  1198. // TDescriptor::GetDescriptorParameter:
  1199. //
  1200. // Get the ae descriptor from the event. If the desired type is not specified, it
  1201. // defaults to typeWildCard
  1202. //----------------------------------------------------------------------------------------
  1203. TDescriptor TDescriptor::GetDescriptorParameter(AEKeyword key, DescType desiredType /*= typeWildCard*/) const
  1204.     {
  1205.     TDescriptor result;
  1206.  
  1207.     //
  1208.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1209.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1210.     // cannot be passed to AEGetParamDesc.
  1211.     //
  1212.     FailErr(AEGetParamDesc(*this, key, desiredType, result));
  1213.     
  1214.     return result;
  1215.     }
  1216.  
  1217. //----------------------------------------------------------------------------------------
  1218. // TDescriptor::GetParameterData: 
  1219. //----------------------------------------------------------------------------------------
  1220. void TDescriptor::GetParameterData(AEKeyword key, TUpdataDataReference& buffer, DescType desiredType /*= typeWildCard*/) const
  1221.     {
  1222.     //
  1223.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1224.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1225.     // cannot be passed to AEGetParamPtr.
  1226.     //
  1227.     DescType actualType;
  1228.     SInt32 actualSize;
  1229.     FailErr(AEGetParamPtr(*this, key, desiredType, &actualType, buffer.Data(), buffer.MaxLength(), &actualSize));
  1230.     buffer.SetDataLength(actualSize);
  1231.     buffer.SetDataType(actualType);
  1232.     } // TDescriptor::GetParameterData 
  1233.  
  1234. //----------------------------------------------------------------------------------------
  1235. // TDescriptor::GetBooleanParameter: 
  1236. //----------------------------------------------------------------------------------------
  1237. Boolean TDescriptor::GetBooleanParameter(AEKeyword key) const
  1238.     {
  1239.     SInt32 result = 0;
  1240.     
  1241.     this->GetParameterData(key, TUpdataDataReference(typeBoolean, (char*)&result, sizeof(Boolean), sizeof(Boolean)), typeBoolean);
  1242.     
  1243.     return result;
  1244.     } // TDescriptor::GetBooleanParameter 
  1245.  
  1246. //----------------------------------------------------------------------------------------
  1247. // TDescriptor::GetSInt32Parameter: 
  1248. //----------------------------------------------------------------------------------------
  1249. SInt32 TDescriptor::GetSInt32Parameter(AEKeyword key) const
  1250.     {
  1251.     SInt32 result = 0;
  1252.     
  1253.     this->GetParameterData(key, TUpdataDataReference(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32)), typeSInt32);
  1254.     
  1255.     return result;
  1256.     } // TDescriptor::GetSInt32Parameter 
  1257.  
  1258. //----------------------------------------------------------------------------------------
  1259. // TDescriptor::GetUInt32Parameter: 
  1260. //----------------------------------------------------------------------------------------
  1261. UInt32 TDescriptor::GetUInt32Parameter(AEKeyword key) const
  1262.     {
  1263.     UInt32 result = 0;
  1264.     
  1265.     this->GetParameterData(key, TUpdataDataReference(typeUInt32, (char*)&result, sizeof(UInt32), sizeof(UInt32)), typeUInt32);
  1266.     
  1267.     return result;
  1268.     } // TDescriptor::GetUInt32Parameter 
  1269.  
  1270. //----------------------------------------------------------------------------------------
  1271. // TDescriptor::GetSInt64Parameter: 
  1272. //----------------------------------------------------------------------------------------
  1273. SInt64 TDescriptor::GetSInt64Parameter(AEKeyword key) const
  1274.     {
  1275.     SInt64 result;
  1276.     
  1277.     this->GetParameterData(key, TUpdataDataReference(typeSInt64, (char*)&result, sizeof(SInt64), sizeof(SInt64)), typeSInt64);
  1278.     
  1279.     return result;
  1280.     } // TDescriptor::GetSInt64Parameter 
  1281.  
  1282. //----------------------------------------------------------------------------------------
  1283. // TDescriptor::GetDescTypeParameter: 
  1284. //----------------------------------------------------------------------------------------
  1285. DescType TDescriptor::GetDescTypeParameter(AEKeyword key, DescType expectedType /*= typeType*/) const
  1286.     {
  1287.     DescType result = 0;
  1288.     
  1289.     this->GetParameterData(key, TUpdataDataReference(expectedType, (char*)&result, sizeof(DescType), sizeof(DescType)), expectedType);
  1290.     
  1291.     return result;
  1292.     } // TDescriptor::GetDescTypeParameter 
  1293.  
  1294. //----------------------------------------------------------------------------------------
  1295. // TDescriptor::GetPSNParameter: 
  1296. //----------------------------------------------------------------------------------------
  1297. ProcessSerialNumber TDescriptor::GetPSNParameter(AEKeyword key) const
  1298.     {
  1299.     ProcessSerialNumber result;
  1300.     
  1301.     this->GetParameterData(key, TUpdataDataReference(typeProcessSerialNumber, (char*)&result, sizeof(ProcessSerialNumber), sizeof(ProcessSerialNumber)), typeProcessSerialNumber);
  1302.     
  1303.     return result;
  1304.     } // TDescriptor::GetPSNParameter 
  1305.  
  1306. //----------------------------------------------------------------------------------------
  1307. // TDescriptor::GetOptionalParameter: 
  1308. // Like 'GetDescriptorParameter, but returns a null descriptor if the specified 
  1309. // parameter could not be extracted.
  1310. //----------------------------------------------------------------------------------------
  1311. TDescriptor TDescriptor::GetOptionalParameter(AEKeyword key, DescType desiredType /*= typeWildCard*/) const
  1312.     {
  1313.     TDescriptor result;
  1314.     OSErr err = noErr;
  1315.  
  1316.     //
  1317.     // It's probably not necessary to call ClearDescriptor if there is
  1318.     // an error, but we might as well be safe (paranoid?).
  1319.     //
  1320.     err = AEGetParamDesc(*this, key, desiredType, result);
  1321.     if(err != noErr)
  1322.         result.ClearDescriptor();
  1323.     
  1324.     return result;
  1325.     } // TDescriptor::GetOptionalParameter 
  1326.  
  1327. //----------------------------------------------------------------------------------------
  1328. // TDescriptor::GetOptionalParameterData
  1329. //----------------------------------------------------------------------------------------
  1330. void TDescriptor::GetOptionalParameterData(AEKeyword key, TUpdataDataReference& buffer, DescType desiredType /*= typeWildCard*/) const
  1331.     {
  1332.     DescType actualType;
  1333.     SInt32 actualSize;
  1334.     if(AEGetParamPtr(*this, key, desiredType, &actualType, buffer.Data(), buffer.MaxLength(), &actualSize) == noErr)
  1335.         {
  1336.         buffer.SetDataLength(actualSize);
  1337.         buffer.SetDataType(actualType);
  1338.         }
  1339.     else
  1340.         {
  1341.         buffer.SetDataLength(0);
  1342.         buffer.SetDataType(typeNull);
  1343.         }
  1344.     }
  1345.  
  1346. //----------------------------------------------------------------------------------------
  1347. // TDescriptor::GetOptionalSInt32Parameter: 
  1348. //----------------------------------------------------------------------------------------
  1349. SInt32 TDescriptor::GetOptionalSInt32Parameter(AEKeyword key, SInt32 defaultValue /*= 0*/) const
  1350.     {
  1351.     SInt32 result = defaultValue;
  1352.     TUpdataDataReference buffer(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32));
  1353.     
  1354.     this->GetOptionalParameterData(key, buffer, typeSInt32);
  1355.     if(buffer.DataType() == typeNull)
  1356.         result = defaultValue;
  1357.     
  1358.     return result;
  1359.     } // TDescriptor::GetOptionalSInt32Parameter 
  1360.  
  1361. //----------------------------------------------------------------------------------------
  1362. // TDescriptor::PutDescriptorParameter: 
  1363. //----------------------------------------------------------------------------------------
  1364. void TDescriptor::PutDescriptorParameter(AEKeyword key, const TDescriptor& data)
  1365.     {
  1366.     FailErr(AEPutParamDesc(*this, key, data));
  1367.     } // TDescriptor::PutDescriptorParameter 
  1368.  
  1369. //----------------------------------------------------------------------------------------
  1370. // TDescriptor::PutParameterData: 
  1371. //----------------------------------------------------------------------------------------
  1372. void TDescriptor::PutParameterData(AEKeyword key, const TAbstractDataReference& data)
  1373.     {
  1374.     FailErr(AEPutParamPtr(*this, key, data.DataType(), data.Data(), data.DataLength()));
  1375.     } // TDescriptor::PutParameterData 
  1376.  
  1377. //----------------------------------------------------------------------------------------
  1378. // TDescriptor::PutBooleanParameter: 
  1379. //----------------------------------------------------------------------------------------
  1380. void TDescriptor::PutBooleanParameter(AEKeyword key, const Boolean& data)
  1381.     {
  1382.     this->PutParameterData(key, TConstDataReference(typeBoolean, (Ptr)&data, sizeof(Boolean)));
  1383.     } // TDescriptor::PutBooleanParameter 
  1384.  
  1385. //----------------------------------------------------------------------------------------
  1386. // TDescriptor::PutSInt32Parameter: 
  1387. //----------------------------------------------------------------------------------------
  1388. void TDescriptor::PutSInt32Parameter(AEKeyword key, const SInt32& data)
  1389.     {
  1390.     this->PutParameterData(key, TConstDataReference(typeSInt32, (Ptr)&data, sizeof(SInt32)));
  1391.     } // TDescriptor::PutSInt32Parameter 
  1392.  
  1393. //----------------------------------------------------------------------------------------
  1394. // TDescriptor::PutUInt32Parameter: 
  1395. //----------------------------------------------------------------------------------------
  1396. void TDescriptor::PutUInt32Parameter(AEKeyword key, const UInt32& data)
  1397.     {
  1398.     this->PutParameterData(key, TConstDataReference(typeUInt32, (Ptr)&data, sizeof(UInt32)));
  1399.     } // TDescriptor::PutUInt32Parameter 
  1400.  
  1401. //----------------------------------------------------------------------------------------
  1402. // TDescriptor::PutSInt64Parameter: 
  1403. //----------------------------------------------------------------------------------------
  1404. void TDescriptor::PutSInt64Parameter(AEKeyword key, const SInt64& data)
  1405.     {
  1406.     this->PutParameterData(key, TConstDataReference(typeSInt64, (Ptr)&data, sizeof(SInt64)));
  1407.     } // TDescriptor::PutSInt64Parameter 
  1408.  
  1409. //----------------------------------------------------------------------------------------
  1410. // TDescriptor::PutDescTypeParameter: 
  1411. //----------------------------------------------------------------------------------------
  1412. void TDescriptor::PutDescTypeParameter(AEKeyword key, const SInt32& data, DescType dataType /*= typeType*/)
  1413.     {
  1414.     this->PutParameterData(key, TConstDataReference(dataType, (Ptr)&data, sizeof(DescType)));
  1415.     } // TDescriptor::PutDescTypeParameter 
  1416.     
  1417. //----------------------------------------------------------------------------------------
  1418. // TDescriptor::PutPSNParameter: 
  1419. //----------------------------------------------------------------------------------------
  1420. void TDescriptor::PutPSNParameter(AEKeyword key, const ProcessSerialNumber& psn)
  1421.     {
  1422.     this->PutParameterData(key, TConstDataReference(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber)));
  1423.     } // TDescriptor::PutPSNParameter 
  1424.  
  1425. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1426. //::  Object specifier methods
  1427. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1428.  
  1429. //----------------------------------------------------------------------------------------
  1430. // TDescriptor::GetObjectSpecifierParameters:
  1431. //----------------------------------------------------------------------------------------
  1432. void TDescriptor::GetObjectSpecifierParameters(DescType& desiredClass, DescType& keyForm, TDescriptor* keyData, TDescriptor* containerDesc) const
  1433.     {
  1434.     TDescriptor thisAsRecord = this->Coerce(typeAERecord);
  1435.         
  1436.     //
  1437.     // Extract the desired class, the key form and the key data from
  1438.     // the object specifier
  1439.     //
  1440.     desiredClass        = thisAsRecord.GetDescTypeParameter(keyAEDesiredClass);
  1441.     keyForm                = thisAsRecord.GetDescTypeParameter(keyAEKeyForm, typeEnumeration);
  1442.     if(keyData != nil)
  1443.         *keyData        = thisAsRecord.GetDescriptorParameter(keyAEKeyData);
  1444.     if(containerDesc != nil)
  1445.         *containerDesc    = thisAsRecord.GetDescriptorParameter(keyAEContainer);
  1446.     
  1447.     thisAsRecord.Dispose();
  1448.     } // TDescriptor::GetObjectSpecifierParameters
  1449.  
  1450. //----------------------------------------------------------------------------------------
  1451. // TDescriptor::MakeObjectSpecifier: 
  1452. //----------------------------------------------------------------------------------------
  1453. void TDescriptor::MakeObjectSpecifier(DescType desiredClass, TDescriptor& container, DescType keyForm, TDescriptor keyData, Boolean disposeInputs)
  1454.     {
  1455.     FailErr(CreateObjSpecifier(desiredClass,container,keyForm,keyData,disposeInputs,*this));
  1456.     } // TDescriptor::MakeObjectSpecifier 
  1457.  
  1458. //----------------------------------------------------------------------------------------
  1459. // TDescriptor::MakeObjectSpecifierForProperty: 
  1460. //----------------------------------------------------------------------------------------
  1461. void TDescriptor::MakeObjectSpecifierForProperty(DescType propertyIdentifier, TDescriptor& container, Boolean disposeInputs)
  1462.     {
  1463.     TDescriptor propertyIDDesc;
  1464.     
  1465.     propertyIDDesc.SetDescTypeData(propertyIdentifier);
  1466.     this->MakeObjectSpecifier(cProperty, container, formPropertyID, propertyIDDesc, disposeInputs);
  1467.     propertyIDDesc.Dispose();
  1468.     } // TDescriptor::MakeObjectSpecifierForProperty
  1469.  
  1470. //----------------------------------------------------------------------------------------
  1471. // TDescriptor::SetDescriptorDataTypeObjectBeingExamined
  1472. //----------------------------------------------------------------------------------------
  1473. void TDescriptor::SetDescriptorDataTypeObjectBeingExamined()
  1474.     {
  1475.     //
  1476.     // 'objectBeingExamined' is a special object specifier that only
  1477.     // has meaning in the context of a comparison descriptor.  Note that
  1478.     // we are copying zero bytes into the data handle of the
  1479.     // "object being examined" descriptor, so it doesn't matter what
  1480.     // address we use here.  It's best to pass in a valid address, though,
  1481.     // as you can never tell if the AEM might decide to dereference the
  1482.     // pointer you give it, even if it doesn't need it.
  1483.     //
  1484.     this->SetDescriptorData(TConstDataReference(typeObjectBeingExamined,(Ptr)this, 0));
  1485.     } // TDescriptor::SetDescriptorDataTypeObjectBeingExamined
  1486.     
  1487. //----------------------------------------------------------------------------------------
  1488. // TDescriptor::MakeSpecifierForPropertyOfObjectBeingExamined: 
  1489. //----------------------------------------------------------------------------------------
  1490. void TDescriptor::MakeSpecifierForPropertyOfObjectBeingExamined(DescType propertyIdentifier)
  1491.     {
  1492.     TDescriptor objectBeingExamined;
  1493.     
  1494.     //
  1495.     // 'objectBeingExamined' is a special object specifier that only
  1496.     // has meaning in the context of a comparison descriptor.  Note that
  1497.     // we are copying zero bytes into the data handle of the
  1498.     // "object being examined" descriptor, so it doesn't matter what
  1499.     // address we use here.  It's best to pass in a valid address, though,
  1500.     // as you can never tell if the AEM might decide to dereference the
  1501.     // pointer you give it, even if it doesn't need it.
  1502.     //
  1503.     objectBeingExamined.SetDescriptorDataTypeObjectBeingExamined();
  1504.     
  1505.     //
  1506.     // result is "propertyIdentifier of (object being examined)"
  1507.     //
  1508.     this->MakeObjectSpecifierForProperty(propertyIdentifier, objectBeingExamined, true);
  1509.     } // TDescriptor::MakeSpecifierForPropertyOfObjectBeingExamined 
  1510.  
  1511. //----------------------------------------------------------------------------------------
  1512. // TDescriptor::MakeCompDescriptor: 
  1513. //----------------------------------------------------------------------------------------
  1514. void TDescriptor::MakeCompDescriptor(DescType comparisonOperator, TDescriptor& comparitor, TDescriptor& compareWith, Boolean disposeInputs)
  1515.     {
  1516.     CreateCompDescriptor(comparisonOperator, comparitor, compareWith, disposeInputs, *this);
  1517.     } // TDescriptor::MakeCompDescriptor 
  1518.  
  1519. //----------------------------------------------------------------------------------------
  1520. // TDescriptor::MakeCompDescriptor: 
  1521. //----------------------------------------------------------------------------------------
  1522. void TDescriptor::MakeCompDescriptor(DescType comparisonOperator, DescType propertyIdentifier, TDescriptor& compareWith, Boolean disposeInputs)
  1523.     {
  1524.     TDescriptor operand1;
  1525.  
  1526.     operand1.MakeSpecifierForPropertyOfObjectBeingExamined(propertyIdentifier);
  1527.  
  1528.     //
  1529.     // Make a compDescriptor of operand1 compared with (comparisonOperator) compareWith
  1530.     //
  1531.     CreateCompDescriptor(comparisonOperator, operand1, compareWith, disposeInputs, *this);
  1532.     operand1.Dispose();
  1533.     } // TDescriptor::MakeCompDescriptor 
  1534.  
  1535.  
  1536. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1537. //::  Object support library
  1538. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1539.  
  1540. TDescriptor gErrorDescriptor;
  1541. Boolean gInstalledErrorCallback = false;
  1542.  
  1543. #ifdef GENERATINGCFM
  1544.     static RoutineDescriptor gGetErrorDescCallbackRD    = BUILD_ROUTINE_DESCRIPTOR(uppOSLGetErrDescProcInfo, TDescriptor::GetErrorDesc);
  1545. #endif
  1546.  
  1547. //----------------------------------------------------------------------------------------
  1548. // TDescriptor::Resolve: 
  1549. //----------------------------------------------------------------------------------------
  1550. TTokenDescriptor TDescriptor::Resolve(const TAETransaction& t, TDescriptor* objectThatCausedError /*= nil*/) const
  1551.     {
  1552.     return TDescriptor::Resolve(t, fCallbackFlags, objectThatCausedError);
  1553.     } // TDescriptor::Resolve 
  1554.  
  1555. //----------------------------------------------------------------------------------------
  1556. // TDescriptor::Resolve:
  1557. //
  1558. // Resolves a list of object specifiers into a list of tokens.  A null descriptor will
  1559. // resolve to a token to the null container.
  1560. //
  1561. // n.b. AEResolve will return an error if you pass it a null descriptor; this is why
  1562. //        we include 'magic' checking for null descriptors here.
  1563. //----------------------------------------------------------------------------------------
  1564. TTokenDescriptor TDescriptor::Resolve(const TAETransaction& t, SInt16 callbackFlags, TDescriptor* objectThatCausedError /*= nil*/) const
  1565.     {
  1566.     TTokenDescriptor resolvedToken;
  1567.     TTokenDescriptor intermediate;
  1568.     
  1569. #if 0 //◊
  1570.     SInt32 startTime = TickCount();
  1571.     SInt32 durration = 0;
  1572. #endif
  1573.     
  1574.     //
  1575.     // First:  special checking for null descriptors
  1576.     //
  1577.     if(this->IsNullDescriptor())
  1578.         {
  1579.         resolvedToken = CreateNullContainerToken();
  1580.         }
  1581.     //
  1582.     // Next, process non-lists
  1583.     //
  1584.     else if(this->DescriptorType() != typeAEList)
  1585.         {
  1586.         //
  1587.         // If a pre-resolve proc was installed, then call it.
  1588.         //
  1589.         // This is where we take over from the OSL and resolve
  1590.         // object specifiers ourselves...
  1591.         //
  1592.         if(gPreResolveProc != nil)
  1593.             {
  1594.             resolvedToken = (*gPreResolveProc)(t, *this, objectThatCausedError);
  1595.             }
  1596.  
  1597.         //
  1598.         // If the pre-resolve proc did not resolve the token,
  1599.         // then call AEResolve
  1600.         //
  1601.         if(resolvedToken.IsNullDescriptor())
  1602.             {
  1603.             if(gInstalledErrorCallback == false)
  1604.                 {
  1605. #ifdef GENERATINGCFM
  1606.                 AEInstallSpecialHandler(keyAEGetErrDescProc, (UniversalProcPtr)&gGetErrorDescCallbackRD, false);
  1607. #else
  1608.                 AEInstallSpecialHandler(keyAEGetErrDescProc, (UniversalProcPtr)TDescriptor::GetErrorDesc, false);
  1609. #endif
  1610.  
  1611.                 gInstalledErrorCallback = true;
  1612.                 }
  1613.             
  1614.             OSErr resolveErr = AEResolve(*this, callbackFlags, resolvedToken);
  1615.             if((resolveErr) != (noErr && objectThatCausedError != nil))
  1616.                 {
  1617.                 objectThatCausedError->AdoptDescriptor(gErrorDescriptor);
  1618.                 gErrorDescriptor.ClearDescriptor();
  1619.                 }
  1620.             else
  1621.                 gErrorDescriptor.Dispose();
  1622.             FailErr(resolveErr);
  1623.             }
  1624.         }
  1625.     //
  1626.     // If we have a list, try to resolve each element of the list in turn
  1627.     //
  1628.     else
  1629.         {
  1630.         OSErr err = noErr;
  1631.         
  1632.         Try
  1633.             {
  1634.             for(TDescriptorIterator iter(*this); iter.More(); iter.Next())
  1635.                 {
  1636.                 //
  1637.                 // We do not want to dispose of the intermediate token descriptor
  1638.                 // because its data is adopted by the 'result' token descriptor.
  1639.                 //
  1640.                 intermediate = iter.Current().Resolve(t, callbackFlags, objectThatCausedError);
  1641.                 resolvedToken.AdoptToken(intermediate);
  1642.                 intermediate.ClearDescriptor();
  1643.                 }
  1644.             }
  1645.         Catch(err)
  1646.             {
  1647.             intermediate.DisposeToken();
  1648.             resolvedToken.DisposeToken();
  1649.             Throw(err);
  1650.             }
  1651.         }
  1652.     
  1653. #if 0 //◊
  1654.     durration = TickCount() - startTime;
  1655. #endif
  1656.     
  1657.     return resolvedToken;
  1658.     } // TDescriptor::Resolve 
  1659.  
  1660. //----------------------------------------------------------------------------------------
  1661. // TDescriptor::GetErrorDesc:
  1662. //
  1663. // Tell the Object support library where it can put a descriptor (an object specifier)
  1664. // to the object that caused the resolution to fail.
  1665. //----------------------------------------------------------------------------------------
  1666. pascal OSErr TDescriptor::GetErrorDesc(TDescriptor** errorDescriptor)
  1667.     {
  1668.     *errorDescriptor = &gErrorDescriptor;
  1669.     
  1670.     return noErr;
  1671.     } // TDescriptor::GetErrorDesc 
  1672.  
  1673. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1674. //::  Old methods
  1675. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1676.  
  1677.  
  1678. //----------------------------------------------------------------------------------------
  1679. // TDescriptor::CoerceToStandardType:
  1680. //
  1681. // This method attempts to coerce its data into some form of standard type
  1682. // (e.g. typeChar or typeLongInteger).  It is really annoying that someone can
  1683. // invent yet another data type that is coercable to text or as a long integer,
  1684. // but we wouldn't have any way to know that such a coercion should be attempted.
  1685. // typeMagnitude and typeEnumeration could throw us for a loop too.
  1686. //
  1687. // ••• In short, I really hate this routine, but I'm not sure what else to do about it.
  1688. //----------------------------------------------------------------------------------------
  1689. TDescriptor TDescriptor::CoerceToStandardType() const
  1690.     {
  1691.     TDescriptor result;
  1692.     
  1693.     switch(this->DescriptorType())
  1694.         {
  1695.         case typeAEText:
  1696.         case typeIntlText:
  1697.         case typeStyledText:
  1698.             {
  1699.             result = this->Coerce(typeChar);
  1700.             break;
  1701.             }
  1702.         
  1703.         case typeShortInteger:
  1704.             {
  1705.             result = this->Coerce(typeLongInteger);
  1706.             break;
  1707.             }
  1708.         }
  1709.     
  1710.     return result;
  1711.     } // TDescriptor::CoerceToStandardType 
  1712.  
  1713. #if BUILDING_PREEMPTIVE_CODE
  1714.  
  1715. //----------------------------------------------------------------------------------------
  1716. // TDescriptor::Lock
  1717. //----------------------------------------------------------------------------------------
  1718. SInt16 TDescriptor::Lock() const
  1719.     {
  1720.     return 0;
  1721.     }
  1722.  
  1723. //----------------------------------------------------------------------------------------
  1724. // TDescriptor::Unlock
  1725. //----------------------------------------------------------------------------------------
  1726. void TDescriptor::Unlock(SInt16 /*oldState*/) const
  1727.     {
  1728.     }
  1729.  
  1730. #else
  1731.  
  1732. //----------------------------------------------------------------------------------------
  1733. // TDescriptor::Lock
  1734. //----------------------------------------------------------------------------------------
  1735. SInt16 TDescriptor::Lock() const
  1736.     {
  1737.     SInt16 result = 0;
  1738.     
  1739.     if(this->DataHandle() != nil)
  1740.         {
  1741.         result = HGetState(this->DataHandle());
  1742.         HLock(this->DataHandle());
  1743.         }
  1744.     
  1745.     return result;
  1746.     }
  1747.  
  1748. //----------------------------------------------------------------------------------------
  1749. // TDescriptor::Unlock
  1750. //----------------------------------------------------------------------------------------
  1751. void TDescriptor::Unlock(SInt16 oldState) const
  1752.     {
  1753.     if(this->DataHandle())
  1754.         HSetState(this->DataHandle(), oldState);
  1755.     }
  1756.  
  1757. #endif
  1758.  
  1759. //========================================================================================
  1760. // CLASS TAEvent
  1761. //
  1762. // AppleEvents are just like AERecords, but they can contain attributes as well as
  1763. // parameters.
  1764. //========================================================================================
  1765.  
  1766. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1767. //::  Event creation
  1768. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1769.  
  1770. //----------------------------------------------------------------------------------------
  1771. // TAEvent::MakeAppleEvent: 
  1772. //----------------------------------------------------------------------------------------
  1773. void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
  1774.                         const AEAddressDesc *target, SInt16 returnID, SInt32 transactionID)
  1775.     {
  1776.     FailErr(AECreateAppleEvent(eventClass, eventID,
  1777.                         target, returnID, transactionID, *this));
  1778.     } // TAEvent::MakeAppleEvent 
  1779.  
  1780. //----------------------------------------------------------------------------------------
  1781. // TAEvent::MakeAppleEvent: 
  1782. //----------------------------------------------------------------------------------------
  1783. void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
  1784.                         const ProcessSerialNumber& psn, SInt16 returnID, SInt32 transactionID)
  1785.     {
  1786.     TDescriptor address;
  1787.     address.SetPSNData(psn);
  1788.     
  1789.     this->MakeAppleEvent(eventClass, eventID, (const AEAddressDesc *) &address, returnID, transactionID);
  1790.     
  1791.     address.Dispose();
  1792.     } // TAEvent::MakeAppleEvent 
  1793.  
  1794.  
  1795. #define kCheckAEM            0
  1796. #define kDontUseSelfSend    1
  1797. #define kSelfSendSafe        2
  1798.  
  1799. SInt16 gCanUseSelfSend = kCheckAEM;
  1800.  
  1801. //----------------------------------------------------------------------------------------
  1802. // TAEvent::MakeEventAddressedToSelf: 
  1803. //----------------------------------------------------------------------------------------
  1804. void TAEvent::MakeEventAddressedToSelf(AEEventClass eventClass, AEEventID eventID, SInt16 returnID, SInt32 transactionID)
  1805.     {
  1806.     ProcessSerialNumber current;        // create psn for self
  1807.     current.highLongOfPSN = 0;
  1808.     current.lowLongOfPSN = kCurrentProcess;
  1809.     
  1810. #if 0 // FOR_SYSTEM7_ONLY
  1811.     //
  1812.     // Old versions of the AEM leak memory if send-to-self is used
  1813.     //
  1814.     if(gCanUseSelfSend == kCheckAEM)
  1815.         {
  1816.         SInt32 aevtSelector = 0;
  1817.         OSErr err = Gestalt('evnt', &aevtSelector);
  1818.         gCanUseSelfSend = ((aevtSelector & 2) != 0) ? kSelfSendSafe : kDontUseSelfSend;
  1819.         }
  1820.     
  1821.     //
  1822.     // Don't make the self-addressed event unless it is safe to do so
  1823.     //
  1824.     if(gCanUseSelfSend == kSelfSendSafe)
  1825.         {
  1826.         this->MakeAppleEvent(eventClass, eventID, current, returnID, transactionID);
  1827.         }
  1828.     else
  1829.         FailErr(errAEEventNotHandled);
  1830. #else
  1831.     this->MakeAppleEvent(eventClass, eventID, current, returnID, transactionID);
  1832. #endif
  1833.     } // TAEvent::MakeEventAddressedToSelf 
  1834.  
  1835. //----------------------------------------------------------------------------------------
  1836. // TAEvent::MakeEventAddressedToSystem: 
  1837. //----------------------------------------------------------------------------------------
  1838. void TAEvent::MakeEventAddressedToSystem(AEEventClass eventClass, AEEventID eventID, SInt16 returnID, SInt32 transactionID)
  1839.     {
  1840.     ProcessSerialNumber systemPSN;        // create psn for the System
  1841.     systemPSN.highLongOfPSN = 0;
  1842.     systemPSN.lowLongOfPSN = kSystemProcess;
  1843.     
  1844.     this->MakeAppleEvent(eventClass, eventID, systemPSN, returnID, transactionID);
  1845.     } // TAEvent::MakeEventAddressedToSystem 
  1846.  
  1847. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1848. //::  Attribute access
  1849. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1850.  
  1851.  
  1852. //----------------------------------------------------------------------------------------
  1853. // TAEvent::GetDescriptorAttribute:
  1854. //
  1855. // Get the ae descriptor from the event. If the desired type is not specified, it
  1856. // defaults to typeWildCard
  1857. //----------------------------------------------------------------------------------------
  1858. TDescriptor TAEvent::GetDescriptorAttribute(AEKeyword key, DescType desiredType /*= typeWildCard*/) const
  1859.     {
  1860.     TDescriptor result;
  1861.  
  1862.     //
  1863.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1864.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1865.     // cannot be passed to AEGetParamDesc.
  1866.     //
  1867.     FailErr(AEGetAttributeDesc(*this, key, desiredType, result));
  1868.     
  1869.     return result;
  1870.     }
  1871.  
  1872. //----------------------------------------------------------------------------------------
  1873. // TAEvent::GetAttributeData: 
  1874. //----------------------------------------------------------------------------------------
  1875. void TAEvent::GetAttributeData(AEKeyword key, TUpdataDataReference& buffer, DescType desiredType /*= typeWildCard*/) const
  1876.     {
  1877.     //
  1878.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1879.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1880.     // cannot be passed to AEGetAttributePtr.
  1881.     //
  1882.     DescType actualType;
  1883.     SInt32 actualSize;
  1884.     FailErr(AEGetAttributePtr(*this, key, desiredType, &actualType, buffer.Data(), buffer.MaxLength(), &actualSize));
  1885.     buffer.SetDataLength(actualSize);
  1886.     buffer.SetDataType(actualType);
  1887.     } // TAEvent::GetAttributeData 
  1888.     
  1889. //----------------------------------------------------------------------------------------
  1890. // TAEvent::GetBooleanAttribute: 
  1891. //----------------------------------------------------------------------------------------
  1892. Boolean TAEvent::GetBooleanAttribute(AEKeyword key) const
  1893.     {
  1894.     SInt32 result = 0;
  1895.     
  1896.     this->GetAttributeData(key, TUpdataDataReference(typeBoolean, (char*)&result, sizeof(Boolean), sizeof(Boolean)), typeBoolean);
  1897.     
  1898.     return result;
  1899.     } // TAEvent::GetBooleanAttribute 
  1900.  
  1901. //----------------------------------------------------------------------------------------
  1902. // TAEvent::GetSInt32Attribute: 
  1903. //----------------------------------------------------------------------------------------
  1904. SInt32 TAEvent::GetSInt32Attribute(AEKeyword key) const
  1905.     {
  1906.     SInt32 result = 0;
  1907.     
  1908.     this->GetAttributeData(key, TUpdataDataReference(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32)), typeSInt32);
  1909.     
  1910.     return result;
  1911.     } // TAEvent::GetSInt32Attribute 
  1912.  
  1913. //----------------------------------------------------------------------------------------
  1914. // TAEvent::GetUInt32Attribute: 
  1915. //----------------------------------------------------------------------------------------
  1916. UInt32 TAEvent::GetUInt32Attribute(AEKeyword key) const
  1917.     {
  1918.     UInt32 result = 0;
  1919.     
  1920.     this->GetAttributeData(key, TUpdataDataReference(typeUInt32, (char*)&result, sizeof(UInt32), sizeof(UInt32)), typeUInt32);
  1921.     
  1922.     return result;
  1923.     } // TAEvent::GetUInt32Attribute 
  1924.  
  1925. //----------------------------------------------------------------------------------------
  1926. // TAEvent::GetSInt64Attribute: 
  1927. //----------------------------------------------------------------------------------------
  1928. SInt64 TAEvent::GetSInt64Attribute(AEKeyword key) const
  1929.     {
  1930.     SInt64 result;
  1931.     
  1932.     this->GetAttributeData(key, TUpdataDataReference(typeSInt64, (char*)&result, sizeof(SInt64), sizeof(SInt64)), typeSInt64);
  1933.     
  1934.     return result;
  1935.     } // TAEvent::GetSInt64Attribute 
  1936.  
  1937. //----------------------------------------------------------------------------------------
  1938. // TAEvent::GetDescTypeAttribute: 
  1939. //----------------------------------------------------------------------------------------
  1940. DescType TAEvent::GetDescTypeAttribute(AEKeyword key, DescType expectedType /*= typeType*/) const
  1941.     {
  1942.     DescType result = 0;
  1943.     
  1944.     this->GetAttributeData(key, TUpdataDataReference(expectedType, (char*)&result, sizeof(DescType), sizeof(DescType)), expectedType);
  1945.     
  1946.     return result;
  1947.     } // TAEvent::GetDescTypeAttribute 
  1948.  
  1949. //----------------------------------------------------------------------------------------
  1950. // TAEvent::GetPSNAttribute: 
  1951. //----------------------------------------------------------------------------------------
  1952. ProcessSerialNumber TAEvent::GetPSNAttribute(AEKeyword key) const
  1953.     {
  1954.     ProcessSerialNumber result;
  1955.     
  1956.     this->GetAttributeData(key, TUpdataDataReference(typeProcessSerialNumber, (char*)&result, sizeof(ProcessSerialNumber), sizeof(ProcessSerialNumber)), typeProcessSerialNumber);
  1957.     
  1958.     return result;
  1959.     } // TAEvent::GetPSNAttribute 
  1960.  
  1961.  
  1962. //----------------------------------------------------------------------------------------
  1963. // TAEvent::GetOptionalAttribute: 
  1964. // Like 'GetDescriptorAttribute, but returns a null descriptor if the specified 
  1965. // Attribute could not be extracted.
  1966. //----------------------------------------------------------------------------------------
  1967. TDescriptor TAEvent::GetOptionalAttribute(AEKeyword key, DescType desiredType /*= typeWildCard*/) const
  1968.     {
  1969.     TDescriptor result;
  1970.     OSErr err = noErr;
  1971.  
  1972.     //
  1973.     // It's probably not necessary to call ClearDescriptor if there is
  1974.     // an error, but we might as well be safe (paranoid?).
  1975.     //
  1976.     err = AEGetAttributeDesc(*this, key, desiredType, result);
  1977.     if(err != noErr)
  1978.         result.ClearDescriptor();
  1979.     
  1980.     return result;
  1981.     } // TAEvent::GetOptionalAttribute 
  1982.  
  1983. //----------------------------------------------------------------------------------------
  1984. // TAEvent::GetOptionalAttributeData
  1985. //----------------------------------------------------------------------------------------
  1986. void TAEvent::GetOptionalAttributeData(AEKeyword key, TUpdataDataReference& buffer, DescType desiredType /*= typeWildCard*/) const
  1987.     {
  1988.     DescType actualType;
  1989.     SInt32 actualSize;
  1990.     if(AEGetAttributePtr(*this, key, desiredType, &actualType, buffer.Data(), buffer.MaxLength(), &actualSize) == noErr)
  1991.         {
  1992.         buffer.SetDataLength(actualSize);
  1993.         buffer.SetDataType(actualType);
  1994.         }
  1995.     else
  1996.         {
  1997.         buffer.SetDataLength(0);
  1998.         buffer.SetDataType(typeNull);
  1999.         }
  2000.     }
  2001.  
  2002. //----------------------------------------------------------------------------------------
  2003. // TAEvent::GetOptionalSInt32Attribute: 
  2004. //----------------------------------------------------------------------------------------
  2005. SInt32 TAEvent::GetOptionalSInt32Attribute(AEKeyword key, SInt32 defaultValue /*= 0*/) const
  2006.     {
  2007.     SInt32 result = defaultValue;
  2008.     TUpdataDataReference buffer(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32));
  2009.     
  2010.     this->GetOptionalAttributeData(key, buffer, typeSInt32);
  2011.     if(buffer.DataType() == typeNull)
  2012.         result = defaultValue;
  2013.     
  2014.     return result;
  2015.     } // TAEvent::GetOptionalSInt32Attribute 
  2016.  
  2017. //----------------------------------------------------------------------------------------
  2018. // TAEvent::PutDescriptorAttribute: 
  2019. //----------------------------------------------------------------------------------------
  2020. void TAEvent::PutDescriptorAttribute(AEKeyword key, const TDescriptor& data)
  2021.     {
  2022.     FailErr(AEPutAttributeDesc(*this, key, data));
  2023.     } // TAEvent::PutDescriptorAttribute 
  2024.  
  2025. //----------------------------------------------------------------------------------------
  2026. // TAEvent::PutAttributeData: 
  2027. //----------------------------------------------------------------------------------------
  2028. void TAEvent::PutAttributeData(AEKeyword key, const TAbstractDataReference& data)
  2029.     {
  2030.     FailErr(AEPutAttributePtr(*this, key, data.DataType(), data.Data(), data.DataLength()));
  2031.     } // TAEvent::PutAttributeData 
  2032.  
  2033. //----------------------------------------------------------------------------------------
  2034. // TAEvent::PutBooleanAttribute: 
  2035. //----------------------------------------------------------------------------------------
  2036. void TAEvent::PutBooleanAttribute(AEKeyword key, const Boolean& data)
  2037.     {
  2038.     this->PutAttributeData(key, TConstDataReference(typeBoolean, (Ptr)&data, sizeof(Boolean)));
  2039.     } // TAEvent::PutBooleanAttribute 
  2040.  
  2041. //----------------------------------------------------------------------------------------
  2042. // TAEvent::PutSInt32Attribute: 
  2043. //----------------------------------------------------------------------------------------
  2044. void TAEvent::PutSInt32Attribute(AEKeyword key, const SInt32& data)
  2045.     {
  2046.     this->PutAttributeData(key, TConstDataReference(typeSInt32, (Ptr)&data, sizeof(SInt32)));
  2047.     } // TAEvent::PutSInt32Attribute 
  2048.  
  2049. //----------------------------------------------------------------------------------------
  2050. // TAEvent::PutUInt32Attribute: 
  2051. //----------------------------------------------------------------------------------------
  2052. void TAEvent::PutUInt32Attribute(AEKeyword key, const UInt32& data)
  2053.     {
  2054.     this->PutAttributeData(key, TConstDataReference(typeUInt32, (Ptr)&data, sizeof(UInt32)));
  2055.     } // TAEvent::PutUInt32Attribute 
  2056.  
  2057. //----------------------------------------------------------------------------------------
  2058. // TAEvent::PutSInt64Attribute: 
  2059. //----------------------------------------------------------------------------------------
  2060. void TAEvent::PutSInt64Attribute(AEKeyword key, const SInt64& data)
  2061.     {
  2062.     this->PutAttributeData(key, TConstDataReference(typeSInt64, (Ptr)&data, sizeof(SInt64)));
  2063.     } // TAEvent::PutSInt64Attribute 
  2064.  
  2065. //----------------------------------------------------------------------------------------
  2066. // TAEvent::PutDescTypeAttribute: 
  2067. //----------------------------------------------------------------------------------------
  2068. void TAEvent::PutDescTypeAttribute(AEKeyword key, const SInt32& data, DescType dataType /*= typeType*/)
  2069.     {
  2070.     this->PutAttributeData(key, TConstDataReference(dataType, (Ptr)&data, sizeof(DescType)));
  2071.     } // TAEvent::PutDescTypeAttribute 
  2072.     
  2073. //----------------------------------------------------------------------------------------
  2074. // TAEvent::PutPSNAttribute: 
  2075. //----------------------------------------------------------------------------------------
  2076. void TAEvent::PutPSNAttribute(AEKeyword key, const ProcessSerialNumber& psn)
  2077.     {
  2078.     this->PutAttributeData(key, TConstDataReference(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber)));
  2079.     } // TAEvent::PutPSNAttribute 
  2080.  
  2081.  
  2082. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2083. //::  Special descriptor access
  2084. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2085.  
  2086.  
  2087. //----------------------------------------------------------------------------------------
  2088. // TAEvent::PutOptionalDescriptorParameter: 
  2089. //----------------------------------------------------------------------------------------
  2090. void TAEvent::PutOptionalDescriptorParameter(AEKeyword key, const TDescriptor& data)
  2091.     {
  2092.     this->PutDescriptorParameter(key, data);
  2093.     this->SpecifyThatParameterIsOptional(key);
  2094.     } // TAEvent::PutOptionalDescriptorParameter 
  2095.  
  2096. //----------------------------------------------------------------------------------------
  2097. // TAEvent::PutOptionalParameterData: 
  2098. //----------------------------------------------------------------------------------------
  2099. void TAEvent::PutOptionalParameterData(AEKeyword key, const TAbstractDataReference& data)
  2100.     {
  2101.     this->PutParameterData(key, data);
  2102.     this->SpecifyThatParameterIsOptional(key);
  2103.     }
  2104.  
  2105. //----------------------------------------------------------------------------------------
  2106. // TAEvent::PutResult: 
  2107. //
  2108. // Put the provided descriptor into the result parameter of this event.  If the data
  2109. // is a null descriptor, then put in an empty list instead.
  2110. //----------------------------------------------------------------------------------------
  2111. void TAEvent::PutResult(const TDescriptor& data)
  2112.     {
  2113.     OSErr err = noErr;
  2114.     
  2115.     //
  2116.     // If this is a null descriptor, it means that the client
  2117.     // doesn't care about the reply, so ignore the result.
  2118.     //
  2119.     if(this->IsNullDescriptor() == false)
  2120.         {
  2121.         //
  2122.         // If there's nothing in the data, then insert an empty list.
  2123.         //
  2124.         if(data.IsNullDescriptor())
  2125.             {
  2126.             TDescriptor emptyList;
  2127.     
  2128.             Try
  2129.                 {
  2130.                 emptyList.CreateList();
  2131.                 this->PutDescriptorParameter(keyAEResult, emptyList);
  2132.                 emptyList.Dispose();
  2133.                 }
  2134.             Catch(err)
  2135.                 {
  2136.                 emptyList.Dispose();
  2137.                 Throw(err);
  2138.                 }
  2139.             }
  2140.         else
  2141.             {
  2142.             this->PutDescriptorParameter(keyAEResult,data);
  2143.             }
  2144.         }
  2145.     } // TAEvent::PutResult 
  2146.  
  2147. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2148. //::  Special-use methods
  2149. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2150.  
  2151.  
  2152. //----------------------------------------------------------------------------------------
  2153. // TAEvent::CanInteractWithUser: 
  2154. //----------------------------------------------------------------------------------------
  2155. Boolean TAEvent::CanInteractWithUser() const
  2156.     {
  2157.     Boolean canInteract = true;
  2158.  
  2159.     TDescriptor interactDesc = this->GetOptionalAttribute(keyInteractLevelAttr, typeEnumerated);
  2160.     if((interactDesc.IsNullDescriptor()) || (interactDesc.GetDescTypeData(typeEnumeration) != 'cans'))
  2161.         canInteract = false;
  2162.     interactDesc.Dispose();
  2163.     
  2164.     return canInteract;
  2165.     } // TAEvent::CanInteractWithUser 
  2166.  
  2167. //----------------------------------------------------------------------------------------
  2168. // TAEvent::ResetTimer: 
  2169. //
  2170. // Note:    requires that this event be a 'reply' event passed to one of our event
  2171. //            handlers by the AppleEvent manager 
  2172. //----------------------------------------------------------------------------------------
  2173. void TAEvent::ResetTimer()
  2174.     {
  2175.     FailErr(AEResetTimer(*this));
  2176.     } // TAEvent::ResetTimer 
  2177.  
  2178. //----------------------------------------------------------------------------------------
  2179. // TAEvent::SpecifyThatParameterIsOptional: 
  2180. //----------------------------------------------------------------------------------------
  2181. void TAEvent::SpecifyThatParameterIsOptional(AEKeyword theOptionalKeyword)
  2182.     {
  2183.     TDescriptor optionalKeywordsList;
  2184.     OSErr err = noErr;
  2185.     
  2186.     Try
  2187.         {
  2188.         //
  2189.         // Try to fetch the keyOptionalKeywordAttr; if it does, then just 
  2190.         // add one more element to the list that is already inside the event.
  2191.         //
  2192.         optionalKeywordsList = this->GetOptionalAttribute(keyOptionalKeywordAttr);
  2193.         if(optionalKeywordsList.IsNullDescriptor())
  2194.             optionalKeywordsList.CreateList();
  2195.         optionalKeywordsList.AddItemToList(TConstDataReference(typeKeyword, (Ptr)&theOptionalKeyword, sizeof(AEKeyword)));
  2196.         this->PutDescriptorAttribute(keyOptionalKeywordAttr, optionalKeywordsList);
  2197.         optionalKeywordsList.Dispose();
  2198.         }
  2199.     Catch(err)
  2200.         {
  2201.         optionalKeywordsList.Dispose();
  2202.         
  2203.         Throw(err);
  2204.         }
  2205.     } // TAEvent::SpecifyThatParameterIsOptional 
  2206.  
  2207.  
  2208. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2209. //::  Send and receive
  2210. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2211.  
  2212. //----------------------------------------------------------------------------------------
  2213. // TAEvent::Send: 
  2214. //----------------------------------------------------------------------------------------
  2215. void TAEvent::Send( TAEvent* reply,
  2216.                     AESendMode sendMode,
  2217.                     AESendPriority sendPriority,
  2218.                     SInt32 timeOutInTicks,
  2219.                     AEIdleUPP idleProc,
  2220.                     AEFilterUPP filterProc)
  2221.     {
  2222.     OSErr err = noErr;
  2223.     
  2224.     err = AESend(*this, *reply, sendMode, sendPriority, timeOutInTicks, idleProc, filterProc);
  2225.     if((err != errAETimeout) || (timeOutInTicks != 0))
  2226.         FailErr(err);
  2227.     } // TAEvent::Send 
  2228.  
  2229. void TAEvent::SendNoReply()
  2230.     {
  2231.     TAEvent reply;
  2232.     
  2233.     this->Send(&reply, kAENoReply);
  2234.     }
  2235.  
  2236. #define kAEDontExecute 0x2000 // for SendMode, when you just want an event recorded, not executed
  2237.  
  2238. //----------------------------------------------------------------------------------------
  2239. // TAEvent::SendNoExecute: 
  2240. //
  2241. // This routine sends the event with the 'kAEDontExecute' bit set, so that the
  2242. // event will be recorded, but the recipient will not execute it.  The event is
  2243. // also sent 'no reply', since it does not make sense to expect a result from
  2244. // a command that is not actually executed.
  2245. //----------------------------------------------------------------------------------------
  2246. void TAEvent::SendNoExecute()
  2247.     {
  2248.     //
  2249.     // The reply isn't actuall filled in due to the kAENoReply flag
  2250.     //
  2251.     TAEvent reply;
  2252.     Send(&reply, kAENoReply+kAEDontExecute);
  2253.     } // TAEvent::SendNoExecute 
  2254.  
  2255. //----------------------------------------------------------------------------------------
  2256. // TAEvent::SuspendTheCurrentEvent: 
  2257. //----------------------------------------------------------------------------------------
  2258. void TAEvent::SuspendTheCurrentEvent()
  2259.     {
  2260.     FailErr(AESuspendTheCurrentEvent(*this));
  2261.     } // TAEvent::SuspendTheCurrentEvent 
  2262.  
  2263. //----------------------------------------------------------------------------------------
  2264. // TAEvent::ResumeTheCurrentEvent: 
  2265. //----------------------------------------------------------------------------------------
  2266. void TAEvent::ResumeTheCurrentEvent(TAEvent* reply, AEEventHandlerUPP dispatcher, SInt32 refCon)
  2267.     {
  2268.     FailErr(AEResumeTheCurrentEvent(*this, *reply, dispatcher, refCon));
  2269.     } // TAEvent::ResumeTheCurrentEvent 
  2270.  
  2271. //----------------------------------------------------------------------------------------
  2272. // TAEvent::SetTheCurrentEvent: 
  2273. //----------------------------------------------------------------------------------------
  2274. void TAEvent::SetTheCurrentEvent()
  2275.     {
  2276.     FailErr(AESetTheCurrentEvent(*this));
  2277.     } // TAEvent::SetTheCurrentEvent 
  2278.  
  2279.  
  2280. //========================================================================================
  2281. // CLASS TDescriptorIterator
  2282. //========================================================================================
  2283.  
  2284. //----------------------------------------------------------------------------------------
  2285. // TDescriptorIterator::~TDescriptorIterator
  2286. //----------------------------------------------------------------------------------------
  2287. TDescriptorIterator::~TDescriptorIterator()
  2288.     {
  2289.     fCurrent.Dispose();
  2290.     }
  2291.     
  2292. //----------------------------------------------------------------------------------------
  2293. // TDescriptorIterator::Reset
  2294. //----------------------------------------------------------------------------------------
  2295. void TDescriptorIterator::Reset(Boolean iterateBackwards /*= false*/)
  2296.     {
  2297.     fCurrent.Dispose();
  2298.     fIterateBackwards = iterateBackwards;
  2299.     if(fIterateBackwards)
  2300.         fCurrentIndex = fCachedCount;
  2301.     else
  2302.         fCurrentIndex = 1;
  2303.     }
  2304.     
  2305. //----------------------------------------------------------------------------------------
  2306. // TDescriptorIterator::More
  2307. //----------------------------------------------------------------------------------------
  2308. Boolean TDescriptorIterator::More() const
  2309.     {
  2310.     return ((fCurrentIndex > 0) && (fCurrentIndex <= fCachedCount));
  2311.     }
  2312.     
  2313. //----------------------------------------------------------------------------------------
  2314. // TDescriptorIterator::Next
  2315. //----------------------------------------------------------------------------------------
  2316. void TDescriptorIterator::Next()
  2317.     {
  2318.     if(this->More())
  2319.         {
  2320.         if(fIterateBackwards)
  2321.             --fCurrentIndex;
  2322.         else
  2323.             ++fCurrentIndex;
  2324.         
  2325.         fCurrent.Dispose();
  2326.         }
  2327.     }
  2328.     
  2329. //----------------------------------------------------------------------------------------
  2330. // TDescriptorIterator::Current
  2331. //----------------------------------------------------------------------------------------
  2332. TDescriptor TDescriptorIterator::Current() const
  2333.     {
  2334.     if(this->More())
  2335.         ((TDescriptorIterator*)this)->fCurrent = fDescriptorList.GetNthItem(fCurrentIndex);
  2336.     return fCurrent;
  2337.     }
  2338.     
  2339. //----------------------------------------------------------------------------------------
  2340. // TDescriptorIterator::OrphanCurrent
  2341. //----------------------------------------------------------------------------------------
  2342. TDescriptor TDescriptorIterator::OrphanCurrent()
  2343.     {
  2344.     TDescriptor result = this->Current();
  2345.     fCurrent.ClearDescriptor();
  2346.     return result;
  2347.     }
  2348.  
  2349. //----------------------------------------------------------------------------------------
  2350. // TDescriptorIterator::CurrentKeyword
  2351. //----------------------------------------------------------------------------------------
  2352. AEKeyword TDescriptorIterator::CurrentKeyword() const
  2353.     {
  2354.     UInt32 unusedBufferspace;
  2355.     AEKeyword resultKeyword = typeWildCard;
  2356.     
  2357.     this->GetCurrentItemData(TUpdataDataReference(typeWildCard, (char*)&unusedBufferspace, 0, 0), typeWildCard, &resultKeyword);
  2358.     
  2359.     return resultKeyword;
  2360.     }
  2361.  
  2362. //----------------------------------------------------------------------------------------
  2363. // TDescriptorIterator::GetCurrentItemData
  2364. //----------------------------------------------------------------------------------------
  2365. void TDescriptorIterator::GetCurrentItemData(TUpdataDataReference& buffer, DescType desiredType /*= typeWildCard*/, AEKeyword* key /*= nil*/) const
  2366.     {
  2367.     if(this->More())
  2368.         {    
  2369.         fDescriptorList.GetNthItemData(fCurrentIndex, buffer, desiredType, key);
  2370.         }
  2371.     else
  2372.         {
  2373.         buffer.SetDataType(typeNull);
  2374.         buffer.SetDataLength(0);
  2375.         if(key != nil)
  2376.             *key = typeNull;
  2377.         }
  2378.     }
  2379.  
  2380. //----------------------------------------------------------------------------------------
  2381. // TDescriptorIterator::GetCurrentBooleanData
  2382. //----------------------------------------------------------------------------------------
  2383. Boolean TDescriptorIterator::GetCurrentBooleanData() const
  2384.     {
  2385.     Boolean result;
  2386.     
  2387.     this->GetCurrentItemData(TUpdataDataReference(typeBoolean, (char*)&result, sizeof(Boolean), sizeof(Boolean)), typeBoolean);
  2388.     
  2389.     return result;
  2390.     }
  2391.  
  2392. //----------------------------------------------------------------------------------------
  2393. // TDescriptorIterator::GetCurrentSInt32Data
  2394. //----------------------------------------------------------------------------------------
  2395. SInt32 TDescriptorIterator::GetCurrentSInt32Data() const
  2396.     {
  2397.     SInt32 result;
  2398.     
  2399.     this->GetCurrentItemData(TUpdataDataReference(typeSInt32, (char*)&result, sizeof(SInt32), sizeof(SInt32)), typeSInt32);
  2400.     
  2401.     return result;
  2402.     }
  2403.     
  2404. //----------------------------------------------------------------------------------------
  2405. // TDescriptorIterator::GetCurrentUInt32Data
  2406. //----------------------------------------------------------------------------------------
  2407. UInt32 TDescriptorIterator::GetCurrentUInt32Data() const
  2408.     {
  2409.     UInt32 result;
  2410.     
  2411.     this->GetCurrentItemData(TUpdataDataReference(typeUInt32, (char*)&result, sizeof(UInt32), sizeof(UInt32)), typeUInt32);
  2412.     
  2413.     return result;
  2414.     }
  2415.     
  2416. //----------------------------------------------------------------------------------------
  2417. // TDescriptorIterator::GetCurrentSInt64Data
  2418. //----------------------------------------------------------------------------------------
  2419. SInt64 TDescriptorIterator::GetCurrentSInt64Data() const
  2420.     {
  2421.     SInt64 result;
  2422.     
  2423.     this->GetCurrentItemData(TUpdataDataReference(typeSInt64, (char*)&result, sizeof(SInt64), sizeof(SInt64)), typeSInt64);
  2424.     
  2425.     return result;
  2426.     }
  2427.     
  2428. //----------------------------------------------------------------------------------------
  2429. // TDescriptorIterator::GetCurrentDescTypeData
  2430. //----------------------------------------------------------------------------------------
  2431. DescType TDescriptorIterator::GetCurrentDescTypeData(DescType expectedType /*= typeType*/) const
  2432.     {
  2433.     DescType result;
  2434.     
  2435.     this->GetCurrentItemData(TUpdataDataReference(expectedType, (char*)&result, sizeof(DescType), sizeof(DescType)), expectedType);
  2436.     
  2437.     return result;
  2438.     }
  2439.  
  2440. //========================================================================================
  2441. // CLASS TTokenDescriptor
  2442. //
  2443. // The class TTokenDescriptor represents descriptors returned by AEResolve
  2444. //========================================================================================
  2445.     
  2446. //----------------------------------------------------------------------------------------
  2447. // TTokenDescriptor::DisposeToken:
  2448. //
  2449. // It is very important that token descriptors be disposed of by AEDisposeToken,
  2450. // _not_ AEDisposeDesc.
  2451. //----------------------------------------------------------------------------------------
  2452. void TTokenDescriptor::DisposeToken()
  2453.     {
  2454.     AEDisposeToken(*this);  // Should fail on error?  Probably not.
  2455.     } // TTokenDescriptor::DisposeToken 
  2456.  
  2457.  
  2458. //----------------------------------------------------------------------------------------
  2459. // TTokenDescriptor::TokenObject:
  2460. //
  2461. // Return the object stored inside the token descriptor
  2462. //----------------------------------------------------------------------------------------
  2463. TAbstractScriptableObject* TTokenDescriptor::TokenObject()
  2464.     {
  2465.     TAbstractScriptableObject* tokenObject = nil;
  2466. #if 0
  2467.     Handle tokenHandle = this->DataHandle();
  2468.     
  2469.     if(this->DescriptorType() == typeTokenObject)
  2470.         {
  2471.         tokenObject = (TAbstractScriptableObject*) tokenHandle;
  2472.         }
  2473.     else
  2474. #endif
  2475.     if(this->DescriptorType() == typeTokenInHandle)
  2476.         {
  2477.         //
  2478.         // tokenHandle is a handle that contains a TTokenObject*,
  2479.         // so it is a pointer to a pointer to a TTokenObject* (wow).
  2480.         // This code is never used if your application supports marking.
  2481.         //
  2482. #if 0
  2483.         tokenObject = ** ((TAbstractScriptableObject***) tokenHandle);
  2484. #endif
  2485.         this->GetDescriptorData(TUpdataDataReference(typeTokenInHandle, (Ptr)&tokenObject, sizeof(Ptr), sizeof(Ptr)));
  2486.         }
  2487.     else if((this->DescriptorType() == typeAEList) && (gMergeTokensProc != nil))
  2488.         {
  2489.         //
  2490.         // This will only happen if the OSL merges tokens into
  2491.         // an AEList for you, which will only happen if your
  2492.         // application does not support marking.
  2493.         //
  2494.         for(TDescriptorIterator iter(*this); iter.More(); iter.Next())
  2495.             {
  2496.             TTokenDescriptor tokenDesc = iter.Current();
  2497.             TAbstractScriptableObject* intermediateObject = tokenDesc.TokenObject();
  2498.             if(tokenObject == nil)
  2499.                 tokenObject = intermediateObject;
  2500.             else
  2501.                 tokenObject = (*gMergeTokensProc)(tokenObject, intermediateObject);
  2502.             }
  2503.         }
  2504.         
  2505.     if(tokenObject == nil)
  2506.         {
  2507.         //
  2508.         // ••• What error code should we fail with here?
  2509.         //
  2510.         FailErr(errAENoSuchObject);
  2511.         }
  2512.     
  2513.     return tokenObject;
  2514.     } // TTokenDescriptor::TokenObject 
  2515.  
  2516.  
  2517. //----------------------------------------------------------------------------------------
  2518. // TTokenDescriptor::AdoptToken:
  2519. //
  2520. // IMPORTANT: ADOPTS THE TOKEN PASSED TO IT
  2521. //----------------------------------------------------------------------------------------
  2522. void TTokenDescriptor::AdoptToken(TTokenDescriptor& tokenDescriptor)
  2523.     {
  2524.     //
  2525.     // Don't adopt the new token if it is empty
  2526.     //
  2527.     if(tokenDescriptor.IsNullDescriptor() == false)
  2528.         {
  2529.         //
  2530.         // If this descriptor is empty, it is easy to adopt the new token
  2531.         //
  2532.         if( this->IsNullDescriptor() )
  2533.             {
  2534.             AdoptDescriptor(tokenDescriptor);
  2535.             }
  2536.         //
  2537.         // If the token being adopted is a list, then append it to us
  2538.         // (we really want to avoid making AELists of AELists).
  2539.         //
  2540.         else if(tokenDescriptor.DescriptorType() == typeAEList)
  2541.             {
  2542.             //
  2543.             // We don't expect to get here any more
  2544.             //
  2545.             ASSERTPRINT(false, ("Got an AEList in TTokenDescriptor::AdoptToken!"));
  2546.             }
  2547.         else
  2548.             {
  2549.             TAbstractScriptableObject* tokenObject = tokenDescriptor.TokenObject();
  2550.             this->AdoptToken(tokenObject);
  2551.             
  2552.             //
  2553.             // n.b.    'Dispose', not 'DisposeToken'.  The token that
  2554.             // was formerly contained in tokenDescriptor is now referenced
  2555.             // in 'this' token descriptor, so it would be a bad idea to
  2556.             // delete it.
  2557.             //
  2558.             tokenDescriptor.Dispose();
  2559.             }
  2560.         }
  2561.     } // TTokenDescriptor::AdoptToken 
  2562.  
  2563. // Boolean gCheatAndInlineToken = false;
  2564.  
  2565. //----------------------------------------------------------------------------------------
  2566. // TTokenDescriptor::AdoptToken: 
  2567. //----------------------------------------------------------------------------------------
  2568. void TTokenDescriptor::AdoptToken(TAbstractScriptableObject* tokenObject)
  2569.     {
  2570.     //
  2571.     // Don't adopt the new token if it is not a valid object
  2572.     //
  2573.     if(tokenObject != nil)
  2574.         {
  2575.         //
  2576.         // If this descriptor is empty, then put the token object
  2577.         // into this token.  If marking is supported, then the
  2578.         // token pointer may be placed into the token directly; if
  2579.         // marking is not supported, then we must create a handle
  2580.         // to hold the token.
  2581.         //
  2582.         if(this->IsNullDescriptor() )
  2583.             {
  2584. #if 0
  2585.             // if((fCallbackFlags & kAEIDoMarking) != 0)
  2586.             if(gCheatAndInlineToken)
  2587.                 this->AdoptHandle(typeTokenObject, (Handle)tokenObject);
  2588.             else
  2589. #endif
  2590.                 {
  2591.                 this->SetDescriptorData(TConstDataReference(typeTokenInHandle, (Ptr)&tokenObject, sizeof(Ptr)));
  2592.                 }
  2593.             }
  2594.         //
  2595.         // If there is already something here, then we need
  2596.         // to somehow merge the two tokens together.
  2597.         // Usually, we want to create a mark token
  2598.         // to do the merge.  However, MoreAEM does not depend
  2599.         // on files such as MarkToken.h which are outside of
  2600.         // the Blue folder.  Therefore, we call a callback proc
  2601.         // to fill in the mark token.  The callback proc is
  2602.         // installed in InitializeScriptability.
  2603.         //
  2604.         else
  2605.             {
  2606.             if(gMergeTokensProc == nil)
  2607.                 FailErr(errAEEventNotHandled);
  2608.                 
  2609.             //
  2610.             // The MergeTokensProc takes two TAbstractScriptableObject*'s
  2611.             // and merges them into another TAbstractScriptableObject*
  2612.             // (which adopts the two original tokens).
  2613.             //
  2614.             TAbstractScriptableObject* mergedTokens = (*gMergeTokensProc)(this->TokenObject(), tokenObject);
  2615.             this->ClearDescriptor();
  2616.             this->AdoptToken(mergedTokens);
  2617.             }
  2618.         }
  2619.     } // TTokenDescriptor::AdoptToken 
  2620.  
  2621. Boolean TDescriptorDataReference::DirectlyReadable() const
  2622. {
  2623.     return true;
  2624. }
  2625.  
  2626.  
  2627. Boolean TDescriptorDataReference::Writable() const
  2628. {
  2629.     return true;
  2630. }
  2631.  
  2632. Boolean TDescriptorDataReference::Resizable() const
  2633. {
  2634.     return true;
  2635. }
  2636.  
  2637. SInt32 TDescriptorDataReference::DataType() const
  2638. {
  2639.     return fDescriptor.DescriptorType();
  2640. }
  2641.  
  2642. SInt32 TDescriptorDataReference::DataLength() const
  2643. {
  2644.     return fDescriptor.DataSize();
  2645. }
  2646.  
  2647. SInt32 TDescriptorDataReference::MaxLength() const
  2648. {
  2649.     return 0x7FFFFFFF;
  2650. }
  2651.  
  2652. SInt32 TDescriptorDataReference::CopyTo(char* destination, SInt32 maxBytesToCopy) const
  2653. {
  2654.     fDescriptor.GetDescriptorData(TUpdataDataReference(typeWildCard, destination, 0, maxBytesToCopy));
  2655.     return this->DataLength();
  2656. }
  2657.  
  2658. Boolean TDescriptorDataReference::CopyFrom(const TAbstractDataReference& source, Boolean)
  2659. {
  2660.     fDescriptor.SetDescriptorData(source);
  2661.     return true;
  2662. }
  2663.  
  2664. const char* TDescriptorDataReference::Data() const
  2665. {
  2666.     char*            inlineData = nil;
  2667.  
  2668.     inlineData = *fDescriptor.DataHandle();
  2669.     
  2670.     return inlineData;
  2671. }
  2672.  
  2673.  
  2674. #if 0
  2675.  
  2676. //========================================================================================
  2677. // CLASS TDescriptorLoop
  2678. //
  2679. // The class TDescriptorLoop is used by the macro FOREACHDESCRIPTOR.  Note that the
  2680. // descriptor returned by "Next" is a copy that must be disposed of by the programmer.
  2681. //
  2682. // We could have TDescriptorLoop keep track of the descriptor it created, and have it
  2683. // dispose it when done.  This would necessitate an 'orphan' method, though, in case
  2684. // someone else wanted to adopt the descriptor.
  2685. //========================================================================================
  2686.  
  2687. #ifdef notinlineconst
  2688. //----------------------------------------------------------------------------------------
  2689. // TDescriptorLoop::TDescriptorLoop: 
  2690. //----------------------------------------------------------------------------------------
  2691. TDescriptorLoop::TDescriptorLoop(const TDescriptor* dl)
  2692.     {
  2693.     fDescriptorList = dl;
  2694.     fIndex = 0;
  2695.     fCount = dl->CountItems();    
  2696.     } // TDescriptorLoop::TDescriptorLoop 
  2697. #endif
  2698. //----------------------------------------------------------------------------------------
  2699. // TDescriptorLoop::Next: 
  2700. //
  2701. // If 'key' is not nil, it is filled in with the keyword from the i'th item of the
  2702. // list (if the list is a record)
  2703. //----------------------------------------------------------------------------------------
  2704. Boolean TDescriptorLoop::Next(TDescriptor& d, AEKeyword* key)
  2705.     {
  2706.     Boolean moreToDo = false;
  2707.     
  2708.     //
  2709.     // Set up on the first time through the loop
  2710.     //
  2711.     if(fIndex == 0)
  2712.         {
  2713.         fCount = fDescriptorList->CountItems();
  2714.         if(d.IsNullDescriptor() == false)
  2715.             {
  2716.             ASSERTPRINT(false, ("TDescriptorLoop::Next:  'd' was not null on first iteration!"));
  2717.             FailErr(errAEEventFailed);
  2718.             }
  2719.         }
  2720.  
  2721.     //
  2722.     // Advance to the next item in the list...
  2723.     //
  2724.     fIndex++;
  2725.     
  2726.     //
  2727.     // Dispose of the 'd' from last time through the loop
  2728.     //
  2729.     d.Dispose();
  2730.     
  2731.     //
  2732.     // Are there still items in the list?
  2733.     //
  2734.     if (fIndex <= fCount)
  2735.         {
  2736.         //
  2737.         // At this point, we could check to see if 'fDescriptorList' actually
  2738.         // points to something that is _not_ a list; if so, we coule return a
  2739.         // _reference_ to the single object, and set a field that indicates that
  2740.         // 'd' is a reference, and should not be disposed next time through the
  2741.         // loop.  The reason we do not do this is that 'd' will be disposed by
  2742.         // the client code if there is a failure, and there is no good way for
  2743.         // the client to know if d is a reference or not.  We could remember
  2744.         // what 'd' was and clean it up in our destructor, but failures can
  2745.         // cause our TDescriptorLoop object to be orphaned without ever being
  2746.         // destructed.
  2747.         //
  2748.         d = fDescriptorList->GetNthItem(fIndex, typeWildCard, key);
  2749.         
  2750.         moreToDo = true;
  2751.         }
  2752.     //
  2753.     // No more items, clean up
  2754.     //
  2755.     else
  2756.         {
  2757.         if(key != nil)
  2758.             *key = typeNull;
  2759.         d.ClearDescriptor();
  2760.         }
  2761.         
  2762.     return moreToDo;
  2763.     } // TDescriptorLoop::Next 
  2764.  
  2765. #endif
  2766.  
  2767.  
  2768.  
  2769. #pragma segment CFrontCruft
  2770.